xm_api_data.h — XM10 Unified Data & Control Interface¶
Header:
XM_FW/XM_API/xm_api_data.h(shared by Rev1.1 / Rev2.0 — the GRF extension fields are 🟢 Rev 2.0 only) Related concept doc: 02. KIT H10 Control & Data (IPO cycle, Body Data, torque sign convention) Related examples: 11 Passive Mode · 12 Active Assist · 13 Resistive · 14 PD Realtime · 16 TinyAI Sensor Fusion · 32 GRF Gait Intent · 41 IMU Hub Dashboard 🛑 Rev 2.0 only · 42 EMG Hub Biofeedback 🛑 Rev 2.0 only
When to use this¶
xm_api_data.h is the facade you will open most often while working on XM10 firmware. Every function that reads the latest state of KIT H10 and the various sensor hubs (GRF, External IMU, IMU Hub, EMG Hub) inside Control_Loop() (XM.status), and every function that issues control commands (XM_Set* / XM_Send*), is declared here.
This page does not re-explain how the global XM object gets filled and flushed (the IPO — Input-Process-Output — cycle), the torque sign convention, or the Body Data prerequisite. If this is your first time, read 02. KIT H10 Control & Data first; use this page to quickly look up function signatures, parameters, and struct fields.
ℹ️ Note on the common
nodeIdparameter: most joint-control functions in this header take aSystemNodeID_t nodeId. In practice only two values are used —SYS_NODE_ID_RH(right hip) andSYS_NODE_ID_LH(left hip). Includingxm_api.halone is enough to use them.
Function List¶
Control Mode · Real-time Torque¶
| Function | One-line description |
|---|---|
XM_SetControlMode() |
Switches whether torque commands are actually sent (monitor / torque control) |
XM_SetAssistTorque() |
Sets both hip assist torques at once |
XM_SetAssistTorqueRH() / XM_SetAssistTorqueLH() |
Sets a single hip's assist torque |
System · Connection Status¶
| Function | One-line description |
|---|---|
XM_IsCmConnected() |
Checks whether communication with the CM is Operational |
XM_GetXMNmtState() |
Returns the detailed connection state with the CM |
Data Transmission (Body Data · PIF-Vector)¶
| Function | One-line description |
|---|---|
XM_SendUserBodyData() |
Sends user body info (weight/height/segment lengths) to the CM |
XM_SendPVector() |
Sends a position-based trajectory (P-Vector) |
XM_SendPVectorReset() |
Immediately cancels an in-progress P-Vector trajectory |
XM_ClearPVectorDoneFlag() |
Manually clears the P-Vector completion flag |
XM_SendIVector() |
Sends impedance control parameters (I-Vector) |
XM_SendFVector() |
Sends a force-based trajectory (F-Vector) |
XM_SendIVectorKpKdMax() |
Sets the Kp/Kd ceiling (the 100% reference) used by I-Vector |
Routines · Parameters¶
| Function | One-line description |
|---|---|
XM_SetDegreeLimitRoutine() / XM_SetDegreeLimit() |
Toggle the angle-limit routine + set upper/lower bounds |
XM_SetVelocityLimitRoutine() / XM_SetVelocityLimit() |
Toggle the angular-velocity-limit routine + set upper/lower bounds |
XM_SetDOBRoutine() |
Toggles the disturbance observer (DOB) routine |
XM_SetNormalCompGain() / XM_SetResistiveCompGain() |
Sets the gravity-compensation / resistive-compensation gain |
XM_SetH10AssistExistingMode() |
Enables/disables H10's built-in (legacy) assist algorithm |
Utility¶
| Function | One-line description |
|---|---|
XM_CaptureLoopCountBase() / XM_GetRelativeLoopCount() |
Captures a baseline for the Assist Loop Count and returns the relative count since then |
23 functions total, plus 3 macros and 13 structs/enums (see Types · Macros below).
Function Details¶
XM_SetControlMode()¶
This is the safety switch that decides whether the robot's output (actuation) is ON or OFF. In both XM_CTRL_MONITOR and XM_CTRL_CONTROL, your Control_Loop() algorithm itself still runs every tick — the only difference is whether the computed torque command is actually sent to the CM. In other words, it is not a switch that turns the algorithm off, only the output.
| Parameter | Type | Description |
|---|---|---|
mode |
XmControlMode_t |
XM_CTRL_MONITOR (default, no output) or XM_CTRL_CONTROL (actual actuation) |
Return value: none
Safety logic: the instant the mode changes (especially MONITOR → TORQUE), all torque commands are internally reset to 0 to prevent a jerk at the start of actuation.
⚠️ Call context: call it from Control_Setup()/Control_Loop(), not from an ISR. The common pattern is XM_CTRL_CONTROL on algorithm Entry and XM_CTRL_MONITOR on Exit.
Example
void Active_Entry(void) {
XM_SetControlMode(XM_CTRL_CONTROL); // start real actuation
}
void Active_Exit(void) {
XM_SetControlMode(XM_CTRL_MONITOR); // safely fall back to monitoring
}
See also: XmControlMode_t
XM_SetAssistTorque()¶
Sets both hip assist torques in one call. The actual CAN transmission happens automatically in the Output stage of the IPO cycle, not inside this function.
| Parameter | Type | Description |
|---|---|---|
rh |
float |
Right (RH) hip assist torque, unit Nm — first argument |
lh |
float |
Left (LH) hip assist torque, unit Nm — second argument |
Return value: none
⚠️ Argument order is (right rh, left lh). If that's confusing, use
XM_SetAssistTorqueRH()/XM_SetAssistTorqueLH()to set one side at a time. For the sign convention, unit, and the hard clamp (±10 Nm), see Doc 02 §Real-time Control — this header itself does not define the scaling/clamp values (they live in another internal module).
⚠️ Call context: assumed to be Control_Loop(). Requires XM_SetControlMode(XM_CTRL_CONTROL) to actually be transmitted.
Example
void Active_Loop(void) {
float cmd_R = XM.status.h10.rightHipAngle * 0.5f; // simple P control
float cmd_L = XM.status.h10.leftHipAngle * 0.5f;
XM_SetAssistTorque(cmd_R, cmd_L);
}
XM_SetAssistTorqueRH() / XM_SetAssistTorqueLH()¶
Sets the assist torque for one leg only. The other leg's torque keeps whatever value was previously set.
| Parameter | Type | Description |
|---|---|---|
rh (RH version) |
float |
Right hip assist torque, unit Nm |
lh (LH version) |
float |
Left hip assist torque, unit Nm |
Return value: none
⚠️ Call context: assumed to be Control_Loop(). Works the same way as XM_SetAssistTorque() by setting an internal Dirty Flag (XmOutput_t._dirty_flags).
Example
XM_IsCmConnected()¶
Checks the communication status with the Control Module (CM).
Return value
| Value | Meaning |
|---|---|
true |
Connection is Operational |
false |
Disconnected, or not yet ready |
⚠️ Call context: assumed to be Control_Setup()/Control_Loop().
Example
See also: XM_GetXMNmtState() — for finer-grained state branching
XM_GetXMNmtState()¶
Returns the detailed connection state with the CM. XM_IsCmConnected() is internally equivalent to checking XM_GetXMNmtState() == CM_NMT_OPERATIONAL.
Return value: CM_NmtState_t (the CM connection-state enum)
| State | Value | Description |
|---|---|---|
CM_NMT_INITIALISING |
0 | Booting (the CM's start-up notice not yet received) |
CM_NMT_PRE_OPERATIONAL |
1 | Configuration messages only; data exchange off |
CM_NMT_OPERATIONAL |
2 | All communication active (normal state) |
CM_NMT_STOPPED |
3 | Communication stopped |
⚠️ Call context: assumed to be Control_Setup()/Control_Loop(). No SDK example currently calls this function directly (XM_IsCmConnected() covers most cases).
XM_SendUserBodyData()¶
Sends the user's body information (weight, height, segment lengths, etc.) to the CM. The CM uses this to improve the accuracy of its real-time gait analysis.
| Parameter | Type | Description |
|---|---|---|
bodyData |
const uint32_t[8] |
An array holding the 8 values below |
Meaning of each bodyData index (units per header comment):
| Index | Description | Unit |
|---|---|---|
| 0 | Wearer's weight | g |
| 1 | Wearer's height | mm |
| 2 | Right thigh segment length | mm |
| 3 | Left thigh segment length | mm |
| 4 | Right shank segment length | mm |
| 5 | Left shank segment length | mm |
| 6 | Right ankle segment length | mm |
| 7 | Left ankle segment length | mm |
Return value: none
⚠️ Call context: Control_Setup() recommended (call once). Body info typically does not change during a session, so there is no need to call this every tick — if omitted, estimated data such as forwardVelocity/leftKneeAngle become inaccurate (see README §Body Data).
Example
void Control_Setup(void) {
uint32_t body_data[8] = {
70000, 1750, 450, 450, 420, 420, 60, 60,
};
XM_SendUserBodyData(body_data);
}
XM_SendPVector()¶
Sends a position-based trajectory (P-Vector) to the specified joint. The motor driver generates a 5th-order polynomial trajectory that smoothly moves to the target position (yd) within the specified time (L).
| Parameter | Type | Description |
|---|---|---|
nodeId |
SystemNodeID_t |
The joint to command (SYS_NODE_ID_RH / SYS_NODE_ID_LH) |
pVector |
const PVector_t* |
Pointer to the P-Vector data struct to send |
Return value: none
⚠️ Impedance parameters must already be configured via XM_SendIVector() beforehand.
⚠️ Call context: assumed to be Control_Loop().
Example
PVector_t pv = { .yd = 250, .L = 1000, .s0 = 4, .sd = 4 }; // target 25.0deg, moves over 1s
XM_SendPVector(SYS_NODE_ID_RH, &pv);
See also: PVector_t
XM_SendPVectorReset()¶
Immediately resets (cancels) the currently running or pending P-Vector command.
| Parameter | Type | Description |
|---|---|---|
nodeId |
SystemNodeID_t |
The joint whose P-Vector should be reset |
Return value: none
⚠️ Call context: assumed to be Control_Loop(). Used for mode transitions / emergency stops.
XM_ClearPVectorDoneFlag()¶
After confirming that XM.status.h10.isPVectorRHDone / isPVectorLHDone has become true and finishing the associated logic, call this manually to signal that you've "consumed" the event.
| Parameter | Type | Description |
|---|---|---|
nodeId |
SystemNodeID_t |
The joint whose completion flag should be cleared |
Return value: none
⚠️ Warning: if you don't call this, the flag stays true and the same completion event may be processed repeatedly.
⚠️ Call context: assumed to be Control_Loop().
XM_SendIVector()¶
Sends impedance control parameters (I-Vector) to the specified joint, making it behave like a virtual spring-damper.
| Parameter | Type | Description |
|---|---|---|
nodeId |
SystemNodeID_t |
The joint to command |
iVector |
const IVector_t* |
Pointer to the impedance parameter struct |
Return value: none
⚠️ Call context: assumed to be Control_Loop(). kp/kd are interpreted as a percentage of the ceiling set by XM_SendIVectorKpKdMax().
Example
IVector_t iv = { .epsilon = 0, .kp = 80, .kd = 1, .lambda = 0, .duration = 50 };
XM_SendIVector(SYS_NODE_ID_RH, &iv);
See also: IVector_t, XM_SendIVectorKpKdMax()
XM_SendFVector()¶
Sends a force-based trajectory (F-Vector) to the specified joint, commanding it to generate a pre-defined torque profile.
| Parameter | Type | Description |
|---|---|---|
nodeId |
SystemNodeID_t |
The joint to command |
fVector |
const FVector_t* |
Pointer to the struct holding target torque / mode info |
Return value: none
⚠️ Call context: assumed to be Control_Loop(). No current SDK example uses this function — the snippet below is an illustrative initialization built purely from the struct's field definitions.
Example
FVector_t fv = { .modeIdx = 1, .tauMax = 500, .delay = 0, .zero = 0 }; // tauMax=5.00A (scaled by 100)
XM_SendFVector(SYS_NODE_ID_RH, &fv);
See also: FVector_t
XM_SendIVectorKpKdMax()¶
Sets the ceiling values applied when XM_SendIVector()'s kp/kd (%) for the specified joint reach 100%.
| Parameter | Type | Description |
|---|---|---|
nodeId |
SystemNodeID_t |
The joint to configure |
kpMax |
const float |
Maximum virtual spring stiffness applied when kp = 100% |
kdMax |
const float |
Maximum virtual damper stiffness applied when kd = 100% |
Return value: none
⚠️ Call context: recommended at Control_Setup() or on state Entry — it must be configured before XM_SendIVector() for the percentage interpretation to make sense.
Example
XM_SendIVectorKpKdMax(SYS_NODE_ID_RH, 6.0f, 1.0f);
XM_SendIVectorKpKdMax(SYS_NODE_ID_LH, 6.0f, 1.0f);
XM_SetDegreeLimitRoutine() / XM_SetDegreeLimit()¶
void XM_SetDegreeLimitRoutine(SystemNodeID_t nodeId, bool isSet);
void XM_SetDegreeLimit(SystemNodeID_t nodeId, float upperLimit, float lowerLimit);
Toggles the angle-limit routine for the specified joint (Routine) and sets its upper/lower bounds (Limit).
| Parameter | Type | Description |
|---|---|---|
nodeId |
SystemNodeID_t |
The joint to configure |
isSet (Routine) |
bool |
true: enable the routine / false: disable |
upperLimit (Limit) |
float |
Upper bound of range of motion, unit degree |
lowerLimit (Limit) |
float |
Lower bound of range of motion, unit degree |
Return value: none
⚠️ Call context: assumed to be Control_Setup()/Control_Loop(). No current SDK example uses this directly.
Example
XM_SetVelocityLimitRoutine() / XM_SetVelocityLimit()¶
void XM_SetVelocityLimitRoutine(SystemNodeID_t nodeId, bool isSet);
void XM_SetVelocityLimit(SystemNodeID_t nodeId, float upperLimit, float lowerLimit);
Toggles the angular-velocity-limit routine for the specified joint and sets its upper/lower bounds.
| Parameter | Type | Description |
|---|---|---|
nodeId |
SystemNodeID_t |
The joint to configure |
isSet (Routine) |
bool |
true: enable the routine / false: disable |
upperLimit (Limit) |
float |
Upper bound of velocity range, unit deg/s |
lowerLimit (Limit) |
float |
Lower bound of velocity range, unit deg/s |
Return value: none
⚠️ Call context: assumed to be Control_Setup()/Control_Loop(). No current SDK example uses this directly.
Example
XM_SetVelocityLimitRoutine(SYS_NODE_ID_LH, true);
XM_SetVelocityLimit(SYS_NODE_ID_LH, 100.0f, -100.0f);
XM_SetDOBRoutine()¶
Enables/disables the disturbance observer (DOB) routine for the specified joint.
| Parameter | Type | Description |
|---|---|---|
nodeId |
SystemNodeID_t |
The joint to configure |
isSet |
bool |
true: enable / false: disable |
Return value: none
⚠️ Call context: assumed to be Control_Setup()/Control_Loop(). No current SDK example uses this directly. Per the header comment, using DOB requires the motor driver side to have completed System Identification.
XM_SetNormalCompGain() / XM_SetResistiveCompGain()¶
void XM_SetNormalCompGain(SystemNodeID_t nodeId, uint8_t gain);
void XM_SetResistiveCompGain(SystemNodeID_t nodeId, float gain);
Adjusts the strength of normal compensation (e.g. gravity compensation) and resistive compensation (resistance-training mode), respectively.
| Parameter | Type | Description |
|---|---|---|
nodeId |
SystemNodeID_t |
The joint to configure |
gain (Normal) |
uint8_t |
Normal compensation gain |
gain (Resistive) |
float |
Resistive compensation gain |
Return value: none
⚠️ Note: the two functions' gain parameters have different types (uint8_t vs float). The header does not separately define a range/scale for either, so pay attention to the integer/float distinction as-is in the signature.
⚠️ Call context: assumed to be Control_Loop(). XM_SetNormalCompGain() currently has no direct SDK example usage.
Example
XM_SetH10AssistExistingMode()¶
Sets whether H10's built-in (legacy) assist algorithm is active. When XM10 and H10 are connected, the default is disabled (XM10 controls directly).
| Parameter | Type | Description |
|---|---|---|
isSet |
bool |
true: enable H10's built-in assist algorithm / false: disable |
Return value: none
⚠️ Call context: assumed to be Control_Setup().
Example
XM_CaptureLoopCountBase() / XM_GetRelativeLoopCount()¶
Stores the h10AssistModeLoopCnt value at the moment of the call as a baseline (0) (Capture), and afterwards returns the count relative to that baseline (GetRelative). Calling this at the start of a data-logging session makes the logged count always start from 0.
Return value (XM_GetRelativeLoopCount): h10AssistModeLoopCnt - baseline. If XM_CaptureLoopCountBase() was never called, the absolute value is returned as-is.
⚠️ Call context: Capture at Control_Setup()/state Entry, GetRelative queried inside Control_Loop(). No current SDK example uses this directly.
Example
void Active_Entry(void) {
XM_CaptureLoopCountBase();
}
void Active_Loop(void) {
uint32_t elapsed = XM_GetRelativeLoopCount(); // relative count starting from 0
myLogData.loopCnt = elapsed;
}
Types · Macros¶
Macros¶
| Macro | Value | Description |
|---|---|---|
XM_GRF_CHANNEL_SIZE |
14 |
Channel count of the legacy GRF (FSR) shoe sensor |
XM_IMU_HUB_SENSOR_COUNT |
6 |
Number of sensors (ports) on the IMU Hub Module |
XM_FES_HUB_CH_COUNT |
2 |
The FES Hub is currently not supported with the XM10. |
XM_GRF_FSR_CH_TOTAL 🟢 Rev 2.0 only |
24 |
FSR channel count of one GRF (foot-sensor) module. Available when you include xm_api.h — Rev1.1 does not have this value |
XmControlMode_t¶
XM10's control-authority (output ON/OFF) mode.
typedef enum {
XM_CTRL_MONITOR = 0, // monitoring mode (default) — algorithm runs, torque command not sent
XM_CTRL_CONTROL = 1 // control mode — computed torque and vector commands are sent periodically (real actuation)
} XmControlMode_t;
| Value | Name | Description |
|---|---|---|
| 0 | XM_CTRL_MONITOR |
Default. The algorithm still runs every tick, but output (actuation) is blocked |
| 1 | XM_CTRL_CONTROL |
The computed torque command is actually sent to the CM |
See also: XM_SetControlMode()
XmH10Mode_t¶
H10 robot's current operating mode (read-only via XM.status.h10.h10Mode).
typedef enum {
XM_H10_MODE_STANDBY = 0, // standby mode (no output)
XM_H10_MODE_ASSIST = 1, // assist mode (torque output)
XM_H10_MODE_UNKNOWN
} XmH10Mode_t;
PVector_t¶
A position-based trajectory command vector. Parameter of XM_SendPVector().
typedef struct {
int16_t yd; // target position, deg×10 scale
uint16_t L; // move duration (ms)
uint8_t s0; // starting acceleration profile (deg/s^2)
uint8_t sd; // ending deceleration profile (deg/s^2)
} PVector_t;
| Field | Type | Unit | Description |
|---|---|---|---|
yd |
int16_t |
deg × 10 | Target position. The header comment states a field-verified example: 25.0deg → 250 |
L |
uint16_t |
ms | Trajectory move duration |
s0 |
uint8_t |
deg/s² | Starting acceleration profile |
sd |
uint8_t |
deg/s² | Ending deceleration profile |
⚠️ Scaling discrepancy to be aware of: some example text in 02. KIT H10 Control & Data still shows
ydas "scaled by 100." The header (xm_api_data.h, the ground truth for this page) explicitly comments "scaled by 10 — field-verified value". Follow this page (the header) when writing code.
IVector_t¶
An impedance-control parameter vector. Parameter of XM_SendIVector().
typedef struct {
uint8_t epsilon; // half width of the corridor (deg×10)
uint8_t kp; // virtual spring magnitude (%)
uint8_t kd; // virtual damper magnitude (%)
uint8_t lambda; // impedance ratio (×100 scale)
uint16_t duration;// transition duration (ms)
} IVector_t;
| Field | Type | Unit | Description |
|---|---|---|---|
epsilon |
uint8_t |
deg × 10 | Half width of the corridor |
kp |
uint8_t |
% | Virtual spring magnitude — percentage of kpMax set via XM_SendIVectorKpKdMax() |
kd |
uint8_t |
% | Virtual damper magnitude — percentage of kdMax |
lambda |
uint8_t |
ratio × 100 | Impedance ratio |
duration |
uint16_t |
ms | Parameter transition time |
FVector_t¶
A force-based trajectory command vector. Parameter of XM_SendFVector().
typedef struct {
uint16_t modeIdx; // torque profile index, 0.1~10
int16_t tauMax; // max torque (A × 100 scale)
uint16_t delay; // initial delay (ms)
uint16_t zero; // dummy data for reset
} FVector_t;
| Field | Type | Unit | Description |
|---|---|---|---|
modeIdx |
uint16_t |
Index (0.1 ~ 10) | Torque profile index (Tp) |
tauMax |
int16_t |
A × 100 | Max torque |
delay |
uint16_t |
ms | Initial delay |
zero |
uint16_t |
- | Dummy data for reset (header comment: "Dummy data for reset") |
XmH10Data_t¶
KIT H10 body data, accessed via XM.status.h10. Includes encoders, joint angles, gait state, and more.
| Field | Type | Unit | Description |
|---|---|---|---|
is_connected |
bool |
- | Communication connection status with H10 |
h10AssistModeLoopCnt |
uint32_t |
- | H10 assist-mode loop count (counts from the start of Assist Mode) |
h10PostProcessingCnt |
uint32_t |
- | GaitAnalysis post-processing sample count (0~30000, for 5m analysis) |
h10Mode |
XmH10Mode_t |
- | H10 operating mode (Assist ↔ Standby) |
h10AssistLevel |
uint8_t |
0~10 | H10 assist level |
h10FSMcurrentState |
uint8_t |
- | H10's current FSM state |
isPVectorRHDone |
bool |
- | RH P-Vector completion flag |
isPVectorLHDone |
bool |
- | LH P-Vector completion flag |
h10IsNeutralPosSet |
bool |
- | H10 neutral-angle setup completion status |
leftHipAngle / rightHipAngle |
float |
deg | Left/right hip angle |
leftThighAngle / rightThighAngle |
float |
deg | Left/right absolute thigh angle |
leftKneeAngle / rightKneeAngle |
float |
deg | Left/right knee angle (estimated) |
pelvicAngle |
float |
deg | Pelvic tilt angle |
isLeftFootContact / isRightFootContact |
bool |
- | Left/right foot ground contact |
forwardVelocity |
float |
m/s | Forward gait velocity |
leftHipTorque / rightHipTorque |
float |
Nm | Estimated joint torque. There is no torque sensor; the value is converted internally from motor current (Kt 0.085 × gear 18.75 ≈ 1.594). It is already converted — do not multiply by Kt again |
leftHipMotorAngle / rightHipMotorAngle |
float |
deg | Left/right motor encoder angle (may differ from joint angle due to gear ratio) |
left/rightHipImuFrontalRoll |
float |
deg | Hip IMU Frontal Roll |
left/rightHipImuSagittalPitch |
float |
deg | Hip IMU Sagittal Pitch |
left/rightHipImuTransverseYaw |
float |
deg | Hip IMU Transverse Yaw |
left/rightHipImuGlobalAccX/Y/Z |
float |
m/s² | Hip IMU global acceleration |
left/rightHipImuGlobalGyrX/Y/Z |
float |
deg/s | Hip IMU global gyroscope |
XM_GRF_SPACE_e¶
Left/right identifier for the legacy GRF (FSR) module.
XmGrfData_t¶
Ground-reaction-force (foot pressure) sensor data, accessed via XM.status.grf. The legacy 14-channel MarvelDex FSR shoe fields are always present; the 🟢 Rev 2.0 only 24-channel fixed-frame (SM-GRF) fields are only included in the struct when the XM_GRF_FIXED_FRAME_MODULE macro is on (Rev 2.0).
| Field | Type | Unit | Description |
|---|---|---|---|
is_left_grf_connected / is_right_grf_connected |
bool |
- | Left/right GRF module connection status |
leftLastUpdateTick / rightLastUpdateTick |
uint32_t |
ms | Left/right data receive timestamp |
leftSensorSpace / rightSensorSpace |
XM_GRF_SPACE_e |
- | 1=left foot, 2=right foot |
leftRollingIndex / rightRollingIndex |
uint8_t |
- | Packet sequence (0~199) |
leftSensorData[14] / rightSensorData[14] |
uint8_t[XM_GRF_CHANNEL_SIZE] |
0~255 raw | 14-channel FSR values |
leftBatteryLevel / rightBatteryLevel |
uint8_t |
0~100 | Battery level |
leftStatusFlags / rightStatusFlags |
uint8_t |
- | Status flags |
leftFsr[24] / rightFsr[24] 🟢 Rev 2.0 only |
uint16_t[XM_GRF_FSR_CH_TOTAL] |
ADC LSB | SM-GRF 24ch FSR raw values (ADC1 15ch + ADC3 9ch) |
leftImu[7] / rightImu[7] 🟢 Rev 2.0 only |
int16_t[7] |
raw | 6-axis IMU raw values in acc[3], gyr[3], temp order |
leftGrfTick / rightGrfTick 🟢 Rev 2.0 only |
uint32_t |
ms | SM-GRF module control tick — used to judge gap/freshness across consecutive receives |
ℹ️ L/R is based on the physical port, not on packet content (header comment: right-foot GRF → XM's right-side port = UART8). This is separate from the legacy fields' "1=left,2=right" discrimination — the Rev 2.0 extension fields are hard-wired to a fixed left/right port.
XmExtImuData_t¶
External UART precision IMU data (currently Xsens MTi-630), accessed via XM.status.ext_imu. The "ext_imu" prefix distinguishes it from the CAN-FD-based IMU Hub, and the name is kept even if the device is swapped for a different UART IMU.
| Field | Type | Unit | Description |
|---|---|---|---|
is_connected |
bool |
- | External IMU connection status |
lastUpdateTick |
uint32_t |
ms | Data receive timestamp |
q_w, q_x, q_y, q_z |
float |
- | Orientation (quaternion) |
acc_x, acc_y, acc_z |
float |
m/s² | Calibrated acceleration |
gyr_x, gyr_y, gyr_z |
float |
deg/s or rad/s | Calibrated gyroscope (header comment lists both units — check per device) |
XmImuHubSensor_t / XmImuHubData_t¶
IMU Hub Module data (EBIMU-9DOFV6 × 6), accessed via XM.status.imu_hub.
The IMU Hub and EMG Hub are modules under internal development. To use them, please contact us at https://huphailab.com/contact.
typedef struct {
float q_w, q_x, q_y, q_z; // orientation (quaternion)
float roll, pitch, yaw; // orientation (Euler, deg)
float acc_x, acc_y, acc_z; // calibrated acceleration (g)
float gyr_x, gyr_y, gyr_z; // calibrated gyroscope (deg/s)
float mag_x, mag_y, mag_z; // calibrated magnetometer (uT)
} XmImuHubSensor_t;
| Field | Type | Unit | Description |
|---|---|---|---|
q_w, q_x, q_y, q_z |
float |
- | Orientation (quaternion) |
roll, pitch, yaw |
float |
deg | Orientation (Euler angles) |
acc_x, acc_y, acc_z |
float |
g | Calibrated acceleration |
gyr_x, gyr_y, gyr_z |
float |
deg/s | Calibrated gyroscope |
mag_x, mag_y, mag_z |
float |
uT | Calibrated magnetometer |
XmImuHubData_t (the top-level struct wrapping all 6 sensors in an array):
| Field | Type | Description |
|---|---|---|
is_connected |
bool |
IMU Hub Module connection status |
lastUpdateTick |
uint32_t |
Data receive timestamp (ms) |
sensor[6] |
XmImuHubSensor_t[XM_IMU_HUB_SENSOR_COUNT] |
IMU sensor data for ports 0~5 |
connected_mask |
uint8_t |
Per-sensor connection bitmask (bit0~5) |
Example (pattern from Ex.41 IMU Hub Dashboard)
const XmImuHubData_t* hub = &XM.status.imu_hub;
if (hub->is_connected) {
float roll0 = hub->sensor[0].roll; // port 0 IMU's Roll (deg)
bool port2_ok = (hub->connected_mask & (1u << 2)) != 0;
}
XmEmgHubData_t¶
EMG Hub Module data (sEMG sensor hub), accessed via XM.status.emg_hub. It holds the results of the 1kHz-sampled HPF 20Hz → rectification → RMS 200ms → envelope 8Hz → MVC → activation pipeline.
| Field | Type | Unit | Description |
|---|---|---|---|
is_connected |
bool |
- | EMG Hub Module connection status |
lastUpdateTick |
uint32_t |
ms | Hub control tick (32-bit, wraps back to 0 after ~49.7 days). If the difference between consecutive receives isn't 1, something was missed. Older hub firmware reports a 24-bit time value instead |
raw_adc |
uint16_t |
12-bit (HW OVS 16×) | Raw ADC value |
voltage_uv |
float |
µV | EMG voltage (AFE-converted) |
rms_uv |
float |
µV | RMS value (200ms sliding window) |
envelope_uv |
float |
µV | Envelope value (EMA fc≈8Hz) |
mvc_percent |
uint8_t |
0~100% | MVC normalization |
is_active |
bool |
- | Muscle contraction detection (Schmitt trigger) |
status_flags |
uint8_t |
bitfield | See the table below |
status_flags bit meanings:
| Bit | Name | Meaning |
|---|---|---|
| bit0 | ADC_OK |
ADC normal |
| bit1 | IS_ACTIVE |
Muscle-contraction detection state |
| bit2 | SATURATED |
Signal saturated |
| bit3 | CALIB_VALID |
MVC calibration valid |
Example (pattern from Ex.42 EMG Hub Biofeedback)
const XmEmgHubData_t* emg = &XM.status.emg_hub;
if (emg->is_connected) {
bool calib_valid = (emg->status_flags & (1u << 3)) != 0U;
uint8_t mvc = emg->mvc_percent;
}
XmFesHubData_t¶
XM.status.fes_hub — The FES Hub is currently not supported with the XM10.
XmInput_t¶
The integrated robot state struct, accessed via XM.status. All read-only sensor data is collected here.
typedef struct {
XmH10Data_t h10; // KIT H10 body data
XmGrfData_t grf; // GRF foot-pressure sensor data
XmExtImuData_t ext_imu; // External UART IMU (Xsens MTi-630)
XmImuHubData_t imu_hub; // IMU Hub sensor data
XmEmgHubData_t emg_hub; // EMG Hub sensor data
XmFesHubData_t fes_hub; // FES Hub (currently not supported with the XM10)
} XmInput_t;
XmOutput_t¶
The robot control command struct, accessed via XM.command.
typedef struct {
XmControlMode_t control_mode;
float assist_torque_rh;
float assist_torque_lh;
struct {
uint8_t torque_rh_updated : 1;
uint8_t torque_lh_updated : 1;
} _dirty_flags;
} XmOutput_t;
| Field | Type | Description |
|---|---|---|
control_mode |
XmControlMode_t |
Current control mode |
assist_torque_rh / assist_torque_lh |
float |
Right/left assist torque (Nm) |
_dirty_flags |
anonymous bitfield struct | ⚠️ Internal only — header comment: "the user doesn't need to know this, the helper functions manage it." Don't write to it directly; always use XM_SetAssistTorque()-family functions |
⚠️ Do not write directly:
XM.commandis a staging area. Assigning to these fields directly does not set the Dirty Flag, so nothing actually gets transmitted. Always use setter functions such asXM_SetAssistTorque().
XmRobot_t (global instance XM)¶
typedef struct {
XmInput_t status; // [Read] sensor values (Input)
XmOutput_t command; // [Write] command values (Output)
} XmRobot_t;
extern XmRobot_t XM;
| Field | Type | Description |
|---|---|---|
status |
XmInput_t |
Read-only sensor data (H10/GRF/ExtIMU/IMU Hub/EMG Hub) |
command |
XmOutput_t |
Write-only control-command staging area — don't write directly, use XM_Set* functions |
Example
Related Documents¶
- 02. KIT H10 Control & Data — IPO cycle, torque sign convention, Body Data details, common mistakes
- README — API Reference Index — full function-group table of contents, per-example Body Data requirements