Skip to main content
When BehaviorConfig.enableMotionLite = true, the Kotlin SDK runs a small classifier on motion features to predict the user’s gross motion state. The Flutter and Swift SDKs ship no model: they emit raw accelerometer samples (emitRawMotionSamples) for the Synheart runtime to classify. This page is the model card for the Kotlin classifier.

Identity

Classes

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.

Inputs

The classifier consumes a fixed-order feature vector derived from windowed sensor buffers:
  • 3-axis acceleration in m/s² (gravity included) and 3-axis gyroscope.
  • Sampling rate: 50 Hz.
  • Window: 5-second windows 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

majorStatePct is the share of windows classified as the major state. confidence is the model’s score for that state; the underlying SVC produces decision scores rather than probabilities, so 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, use the runtime’s motion classifier: on Flutter or Swift, set emitRawMotionSamples = true and forward the samples to the Synheart runtime.

Runtime considerations

When the model is and is not loaded

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 motion sensors 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. Flutter and Swift already rely on it: set BehaviorConfig.emitRawMotionSamples = true and read motion state from the runtime’s HSI emit. The Kotlin SDK’s Linear SVC remains for direct consumers.