Skip to content
CARP Docs
Ask AISystemLightDark
On this page

Measure types

The seven Polar measure types, their sample rates, timestamps and data fields.

Copy MarkdownOpen inOpen in GitHubView as MarkdownOpen in Scira AIOpen in ChatGPTOpen in ClaudeOpen in Cursor

carp_polar_package has seven measure types in the dk.cachet.carp.polar namespace, for heart rate, ECG, photoplethysmography (PPG), pulse-to-pulse intervals (PPI) and motion. Add each one to a protocol as Measure(type: PolarSamplingPackage.<constant>), in a task that runs on a PolarDevice:

Measure typeConstantKindAndroidiOS
dk.cachet.carp.polar.hrHREvent-basedYesYes
dk.cachet.carp.polar.ecgECGEvent-basedYesYes
dk.cachet.carp.polar.accelerometerACCELEROMETEREvent-basedYesYes
dk.cachet.carp.polar.gyroscopeGYROSCOPEEvent-basedYesYes
dk.cachet.carp.polar.magnetometerMAGNETOMETEREvent-basedYesYes
dk.cachet.carp.polar.ppgPPGEvent-basedYesYes
dk.cachet.carp.polar.ppiPPIEvent-basedYesYes

All seven are event-based; see Event-based and one-time measures. They stream from the moment their task starts until it is paused.

Add them to a BackgroundTask with an ImmediateTrigger, and they start when the sensor connects. For a known issue in version 2.1.0, see Connect to the sensor. Which of them produce data depends on the sensor model; see Supported models.

Each measurement holds one batch of samples, as the sensor sent it. For the measurement envelope around the data, see Measurements and data.

Sample rates and ranges

None of the measures has a sampling configuration, so overrideSamplingConfiguration has no effect.

For ECG, acceleration, angular velocity, magnetic field and PPG, the polar plugin asks the sensor which settings it offers. It then selects the highest sample rate, range and resolution. Heart rate and PPI have no settings.

Polar's documentation of the H10 and the Verity Sense gives these highest settings:

MeasureSensorSample rateRange
ECGH10130 Hz—
AccelerationH10200 Hz±8 g
AccelerationVerity Sense52 Hz±8 g
Angular velocityVerity Sense52 Hz±2000 degrees per second
Magnetic fieldVerity Sense100 Hz±50 gauss
PPGVerity Sense55 Hz—

CARP Mobile Sensing (CAMS) cannot select lower settings. It also does not turn on the SDK mode of the Verity Sense, which offers more rates and ranges.

Timestamps

The sensorStartTime of each measurement is the phone time, in microseconds since the Unix epoch, when the batch reached CAMS. Polar measurements have no sensorEndTime.

ECG, acceleration, angular velocity, magnetic field and PPG samples also have a timeStamp from the sensor's clock. Heart rate and PPI samples have no time of their own.

The sensor counts its time in nanoseconds since 1 January 2000. The polar plugin converts this count to a local date and time, starting from midnight on that day in the phone's time zone. CAMS writes timeStamp in ISO 8601 without a UTC offset, for example 2026-10-26T15:03:12.103692.

CAMS does not set the sensor's clock. The H10 resets its clock to a default time whenever it shuts down, so timeStamp may be far from the real time. To align Polar data with other data, use sensorStartTime.

Heart rate

dk.cachet.carp.polar.hr streams the heart rate that the sensor computes. The H10 and H9 also report RR intervals: the times between heartbeats.

Each measurement is a PolarHR with a list of PolarHRSample in samples. Each sample has these fields:

FieldTypeDescription
hrintHeart rate in beats per minute.
rrsMsList<int>RR intervals in milliseconds. May be empty.
contactStatusbooltrue if the sensor has contact with the skin.
contactStatusSupportedbooltrue if the sensor can detect skin contact.

The polar plugin also reports a PPG quality value and a corrected heart rate, which CAMS does not store.

Example data
{
  "__type": "dk.cachet.carp.polar.hr",
  "samples": [
    {
      "hr": 64,
      "rrsMs": [938],
      "contactStatus": true,
      "contactStatusSupported": true
    }
  ]
}

ECG

dk.cachet.carp.polar.ecg streams a single-lead ECG from the H10 at 130 Hz. Polar describes the signal in H10_ECG_Explained.pdf, which comes with the package.

Each measurement is a PolarECG with a list of PolarECGSample in samples. Each sample has these fields:

FieldTypeDescription
timeStampDateTimeTime of the sample from the sensor's clock, in ISO 8601 local time.
voltageintECG voltage in microvolts (µV).
Example data
{
  "__type": "dk.cachet.carp.polar.ecg",
  "samples": [
    { "timeStamp": "2026-10-26T15:03:12.096154", "voltage": -54 },
    { "timeStamp": "2026-10-26T15:03:12.103846", "voltage": -42 },
    { "timeStamp": "2026-10-26T15:03:12.111538", "voltage": -12 }
  ]
}

Acceleration

dk.cachet.carp.polar.accelerometer streams acceleration on three axes, including gravity, from the H10 and the Verity Sense.

Each measurement is a PolarAccelerometer with a list of PolarAccelerometerSample in samples. Each sample has these fields:

FieldTypeDescription
timeStampDateTimeTime of the sample from the sensor's clock, in ISO 8601 local time.
xintAcceleration along the x axis in milli-g, including gravity.
yintAcceleration along the y axis in milli-g, including gravity.
zintAcceleration along the z axis in milli-g, including gravity.
Example data
{
  "__type": "dk.cachet.carp.polar.accelerometer",
  "samples": [
    { "timeStamp": "2026-10-26T15:03:12.104692", "x": -23, "y": 980, "z": 105 },
    { "timeStamp": "2026-10-26T15:03:12.109692", "x": -21, "y": 983, "z": 101 }
  ]
}

Angular velocity

dk.cachet.carp.polar.gyroscope streams the angular velocity on three axes from the Verity Sense.

Each measurement is a PolarGyroscope with a list of PolarGyroscopeSample in samples. Each sample has these fields:

FieldTypeDescription
timeStampDateTimeTime of the sample from the sensor's clock, in ISO 8601 local time.
xdoubleAngular velocity around the x axis in degrees per second.
ydoubleAngular velocity around the y axis in degrees per second.
zdoubleAngular velocity around the z axis in degrees per second.
Example data
{
  "__type": "dk.cachet.carp.polar.gyroscope",
  "samples": [
    { "timeStamp": "2026-10-26T15:03:12.104692", "x": 1.22, "y": -0.61, "z": 0.0 }
  ]
}

Magnetic field

dk.cachet.carp.polar.magnetometer streams the magnetic field on three axes from the Verity Sense.

Each measurement is a PolarMagnetometer with a list of PolarMagnetometerSample in samples. Each sample has these fields:

FieldTypeDescription
timeStampDateTimeTime of the sample from the sensor's clock, in ISO 8601 local time.
xdoubleMagnetic field along the x axis in gauss.
ydoubleMagnetic field along the y axis in gauss.
zdoubleMagnetic field along the z axis in gauss.
Example data
{
  "__type": "dk.cachet.carp.polar.magnetometer",
  "samples": [
    { "timeStamp": "2026-10-26T15:03:12.104692", "x": 0.213, "y": -0.402, "z": 0.155 }
  ]
}

Photoplethysmography

dk.cachet.carp.polar.ppg streams the raw signals of the optical heart rate sensor of the Verity Sense. The signals measure the light that the skin reflects, which changes with the blood volume under it.

Each measurement is a PolarPPG with these fields:

FieldTypeDescription
typePpgDataTypeThe layout of the optical channels: ppg3_ambient1, with three PPG channels and one ambient light channel, or unknown.
samplesList<PolarPPGSample>The samples in the batch.

Each PolarPPGSample has these fields:

FieldTypeDescription
timeStampDateTimeTime of the sample from the sensor's clock, in ISO 8601 local time.
channelSamplesList<int>One raw sensor value per channel.
Example data
{
  "__type": "dk.cachet.carp.polar.ppg",
  "samples": [
    {
      "timeStamp": "2026-10-26T15:03:12.104692",
      "channelSamples": [263464, 270146, 255894, 2385]
    }
  ],
  "type": "ppg3_ambient1"
}

Pulse-to-pulse intervals

dk.cachet.carp.polar.ppi streams the pulse-to-pulse intervals that the Verity Sense derives from its optical signal: the time from one pulse to the next. Polar's documentation of the Verity Sense notes three things:

  • the first batch arrives about 25 seconds after the stream starts;
  • while PPI runs, the heart rate updates only every 5 seconds;
  • the skin contact detection is unreliable, so do not rely on skinContactStatus.

Each measurement is a PolarPPI with a list of PolarPPISample in samples. The samples have no time of their own. Each sample has these fields:

FieldTypeDescription
ppiintPulse-to-pulse interval in milliseconds.
errorEstimateintExpected absolute error of ppi in milliseconds. Below 10 ms, the interval is probably very accurate. Above 30 ms, movement or loose contact may have disturbed it.
hrintHeart rate in beats per minute.
blockerBitbooltrue if the interval is invalid, for example because of movement.
skinContactStatusboolfalse if the sensor detects poor or no skin contact.
skinContactSupportedbooltrue if the sensor can detect skin contact.
Example data
{
  "__type": "dk.cachet.carp.polar.ppi",
  "samples": [
    {
      "ppi": 875,
      "errorEstimate": 6,
      "hr": 68,
      "blockerBit": false,
      "skinContactStatus": true,
      "skinContactSupported": true
    }
  ]
}

Quick links

Page · DocumentationCARP DocumentationPage · DocumentationIntroductionPage · DocumentationQuickstartPage · DocumentationTerminologyPage · DocumentationArchitecture