Documentation Index
Fetch the complete documentation index at: https://docs.synheart.ai/llms.txt
Use this file to discover all available pages before exploring further.
When BehaviorConfig.enableMotionLite = true, the SDK runs a small classifier on accelerometer features to predict the user’s gross motion state. This page is the model card.
Identity
| Attribute | Value |
|---|
| Family | Linear Support Vector Classifier (One-vs-Rest) |
| Format | ONNX |
| Asset path | assets/models/linear_svc_model.onnx (Android) / bundled equivalents on iOS and Dart |
| Runtime | ONNX Runtime (ai.onnxruntime on Android, native onnxruntime framework on iOS) |
| Class count | 4 |
| Latency target | < 5 ms per inference on a modern mid-range device |
| Distribution | Bundled in the SDK; no network calls; no over-the-air updates |
Classes
["LAYING", "MOVING", "SITTING", "STANDING"]
These are the only labels the SDK emits today. The class list is loaded from the model’s label asset on init; mismatches against the model’s output dimension cause init to fail loudly.
The classifier consumes a fixed-order feature vector derived from a windowed accelerometer buffer:
- 3-axis acceleration in m/s² (gravity included).
- Sampling rate: native motion collector at the platform’s max — typically 50 Hz.
- Window: a rolling buffer the SDK aggregates into derived features.
The exact set of derived features (statistical moments, jerk magnitudes, axis correlations, gravity-removed components, etc.) is owned by the SDK’s MotionFeatureExtractor — refer to source for the authoritative list.
Outputs
class MotionState {
final String majorState; // one of the four labels
final double majorStatePct; // probability mass on major state
final Map<String, double> perStateConfidence; // class probabilities
}
majorStatePct comes from the model’s calibration head (a softmax-style normalisation since the underlying SVC produces decision scores rather than probabilities). Treat it as a heuristic, not a calibrated posterior.
Training context
- The model file is shipped as ONNX, exported from
scikit-learn (Linear SVC with one-vs-rest).
- Training data, train/test splits, fairness metrics, and demographic coverage are not documented in the SDK source. Treat the classifier as a fast best-effort component, not a clinical sensor.
When you need stronger guarantees, switch to the runtime’s on-device motion classifier by setting emitRawMotionSamples = true and forwarding samples to the Synheart runtime via pushAccel.
Runtime considerations
| Concern | Behavior |
|---|
| Thread | Inference runs on a background dispatcher. Results delivered back on the main isolate / main queue. |
| Battery | Continuous 50 Hz collection is the primary cost — much higher than the inference itself. Disable when not needed. |
| Memory | Model bytes loaded once on loadModel(); ORT session retained for the SDK’s lifetime. |
| Cold start | First inference includes ORT environment + session init; subsequent inferences are pure compute. |
| Failure modes | If the model fails to load (asset missing, ORT init error), the SDK logs and motionState is permanently null for the session. |
When the model is and is not loaded
| Condition | Loaded? |
|---|
BehaviorConfig.enableMotionLite = false (default) | No — collectors don’t run, no inference. |
enableMotionLite = true | Loaded lazily on initialize(). |
emitRawMotionSamples = true && enableMotionLite = false | Not loaded — the SDK only forwards raw samples to the host. |
Both true | Loaded; the SDK’s classifier and the host-side runtime classifier run side-by-side. |
Known limits
- No gait variants. “MOVING” is a single class; the SDK does not distinguish walking, running, cycling, or vehicle motion.
- Posture vs activity. “SITTING” vs “STANDING” relies on gravity decomposition, which is sensitive to phone orientation. A phone flat on a desk reads differently from one in a pocket.
- No biometric calibration. The classifier does not adapt per user.
- No location or transport context. Inputs are accelerometer-only; “MOVING” inside a vehicle is detected the same as walking.
- Charging stationary cases. A phone left charging on a flat surface typically classifies as “LAYING”.
- No confidence threshold. The SDK returns whichever class has the highest score; downstream consumers should apply their own threshold using
majorStatePct if they want to drop low-confidence predictions.
Migration path
The runtime’s MotionStateHead is the long-term replacement. Apps consuming synheart-core should already prefer:
- Set
BehaviorConfig.emitRawMotionSamples = true.
- Set
BehaviorConfig.enableMotionLite = false.
- Read motion state from the runtime’s HSI emit.
The SDK’s Linear SVC remains for direct consumers and for the migration window.