Android 传感器

1,488 阅读16分钟

1. 传感器坐标轴

1.1 移动设备坐标轴

Sensor API 仅与屏幕的自然方向相关(当设备的屏幕方向更改时,坐标轴不会发生交换。)

移动设备的 Sensor API 坐标系

1.2 汽车坐标轴

在 Android Automotive 实现中,坐标轴相对于车身坐标系进行定义。

汽车设备的 Sensor API 坐标系

图 2. Sensor API 使用的坐标系(相对于汽车设备)

  • X 轴沿车辆右侧延伸
  • Y 轴沿车架前方延伸
  • Z 轴沿车架顶部延伸

坐标系的原点位于车辆后轴的中心。从坐标轴的正方向观察时,正旋转方向为逆时针方向。因此,当车辆向左转时,Z 轴的陀螺仪转速应该为正值。

1.3 SensorManager

SensorManager sensorManager = (SensorManager)getSystemService(Context.SENSOR_SERVICE); sensorManager.regesterListener(SensorEventListener listener, Sensor sensor, int rate); 第一个参数为传感器监听 第二个参数为当前注册的传感器 第三个参数是延迟时间的精密度, 精密度可选择的值:

1.SensorManager.SENSOR_DELAY_FASTEST // 0ms

2.SensorManager.SENSOR_DELAY_GAME // 20ms

3.SensorManager.SENSOR_DELAY_UI // 60ms

4.SensorManager.SENSOR_DELAY_NORMAL // 200ms

2. 基础传感器

基础传感器类型以其代表的物理传感器命名。这些传感器会转发来自单个物理传感器的数据(与通过其他传感器生成数据的复合传感器相反)。基础传感器类型的示例包括:

  • SENSOR_TYPE_ACCELEROMETER
  • SENSOR_TYPE_GYROSCOPE
  • SENSOR_TYPE_MAGNETOMETER

不过,基础传感器不等同于其底层物理传感器,也不得与这些传感器相混淆。来自基础传感器的数据不是物理传感器的原始输出信息,因为数据已进行了校正(如偏差补偿和温度补偿)。

2.1 加速度传感器

getDefaultSensor(SENSOR_TYPE_ACCELEROMETER) 返回非唤醒传感器

加速度计传感器可报告设备沿三个传感器坐标轴的加速度。测量的加速度包括物理加速度(速度变化)和重力加速度。测量结果在 sensor_event_t.acceleration 的 x、y 和 z 字段中报告。所有值均采用国际单位制单位 (m/s^2),测量结果为设备加速度减去沿三个传感器坐标轴的重力加速度。

  • 当设备平放在桌子上并从其左侧向右推动时,x 轴加速度值为正。
  • 当设备平放在桌子上时,z 轴上的加速度值为 +9.81,相当于设备的加速度 (0 m/s^2) 减去重力加速度 (-9.81 m/s^2)。
  • 当设备平放在桌子上并向上抬起时,加速度值大于 +9.81,相当于设备的加速度 (+A m/s^2) 减去重力加速度 (-9.81 m/s^2)。

2.2 环境温度传感器

getDefaultSensor(SENSOR_TYPE_AMBIENT_TEMPERATURE) 返回非唤醒传感器

该传感器可提供环境(室内)温度,单位是摄氏度。

2.3 磁场传感器

getDefaultSensor(SENSOR_TYPE_MAGNETIC_FIELD) 返回非唤醒传感器

SENSOR_TYPE_GEOMAGNETIC_FIELD == SENSOR_TYPE_MAGNETIC_FIELD

磁场传感器(也称为磁力计)可报告沿三个传感器坐标轴测量的环境磁场。

测量结果在 sensors_event_t.magnetic 的 x、y 和 z 字段中报告,且所有值单位均是微特斯拉 (uT)。

磁力计还通过 sensors_event_t.magnetic.status 报告其预测的读数精度。如需详细了解此字段的可能值,请参阅 SensorManagerSENSOR_STATUS_* 常量。

2.4 陀螺仪

getDefaultSensor(SENSOR_TYPE_GYROSCOPE) 返回非唤醒传感器

陀螺传感器可报告设备围绕三个传感器坐标轴的旋转速率。

逆时针方向为正转方向(右手定则)。 即,如果位于原点的设备逆时针旋转,观察者从设备 x、y 或 z 轴某个正向位置看过去,将报告设备呈正向旋转。请注意,这是正向旋转的标准数学定义,与航空航天领域对转动的定义并不一致。

测量结果在 sensors_event_t.gyro 的 x、y 和 z 字段中报告,且所有值的单位均为每秒转动弧度 (rad/s)。

2.5 心率传感器

getDefaultSensor(SENSOR_TYPE_HEART_RATE) 返回非唤醒传感器

心率传感器可报告触摸设备的人员当前的心率。

以每分钟心跳次数 (BPM) 表示的当前心率在 sensors_event_t.heart_rate.bpm 中报告,而传感器的状态在 sensors_event_t.heart_rate.status 中报告。如需详细了解此字段的可能值,请参阅 SensorManagerSENSOR_STATUS_* 常量。特别是在第一次激活时,除非已知不会随身携带设备,否则首次事件的状态字段必须设置为 SENSOR_STATUS_UNRELIABLE。因为传感器采用变化模式,当且仅当 heart_rate.bpmheart_rate.status 自上次事件后已发生变化时才会触发事件。事件生成速度不会大于每隔 sampling_period 一次。

sensor_t.requiredPermission 始终为 SENSOR_PERMISSION_BODY_SENSORS

2.6 光线传感器

getDefaultSensor(SENSOR_TYPE_LIGHT) 返回非唤醒传感器

光线传感器可报告当前照明度,采用国际单位勒克斯 (lux)。

测量结果在 sensors_event_t.light 中报告。

2.7 近程传感器

通常定义为唤醒传感器

getDefaultSensor(SENSOR_TYPE_PROXIMITY) 返回唤醒传感器

近程传感器可报告从传感器到最近的可见表面的距离。

在 Android 4.4 或更早版本中,近程传感器一直是唤醒传感器,也就是说,此类传感器在检测到近程距离发生变化时会唤醒 SoC。对于 Android 4.4 之后的版本,我们建议您首先实现该传感器的唤醒版本,因为该版本在打电话时用于开启和关闭屏幕。

测量结果在 sensors_event_t.distance 中报告(以厘米为单位)。请注意,一些近程传感器仅支持“近”或“远”二元测量结果。在此情况下,传感器检测到“远”状态时报告值 sensor_t.maxRange,检测到“近”状态时报告一个小于 sensor_t.maxRange 的值。

2.8 压力传感器

getDefaultSensor(SENSOR_TYPE_PRESSURE) 返回非唤醒传感器

压力传感器(也称为气压计)可报告大气压力,以百帕斯卡 (hPa) 为单位。

使用以下参数校准读数:

  • 温度补偿
  • 出厂偏差校准
  • 出厂尺度校准

气压计通常用于估算高度变化。 要估算绝对高度,必须将海平面压力(随天气变化)作为参照点。

2.9 相对湿度传感器

getDefaultSensor(SENSOR_TYPE_RELATIVE_HUMIDITY) 返回非唤醒传感器

相对湿度传感器用于测量环境空气相对湿度,并返回百分比值。

3. 复合传感器

3.1 线性加速器

底层物理传感器:加速度计和(如有)陀螺仪(或如果陀螺仪不存在,则使用磁力计)

报告模式:连续模式

getDefaultSensor(SENSOR_TYPE_LINEAR_ACCELERATION) 返回非唤醒传感器

线性加速度传感器可报告传感器框架内设备的线性加速度(不包括重力加速度)。

从概念上看,输出结果为:加速度计的输出结果减去重力传感器的输出结果。结果在 sensors_event_t.acceleration 的 x、y 和 z 字段中报告,单位为 m/s^2。

当设备不动时,所有轴上的读数应接近 0。

如果设备配备陀螺仪,则线性加速度传感器必须将陀螺仪和加速度计作为输入源。

如果设备未配备陀螺仪,则线性加速度传感器必须将加速度计和磁力计作为输入源。

3.2 大幅度动作传感器

底层物理传感器:加速度计(或其他低功耗的传感器)

报告模式:单次模式

低功耗

仅实现该传感器的唤醒版本。

getDefaultSensor(SENSOR_TYPE_SIGNIFICANT_MOTION) 返回唤醒传感器

当检测到大幅度动作时,会触发大幅度动作传感器;大幅度动作是指可能导致用户位置发生变化的动作。

此类大幅度动作示例如下:

  • 步行或骑自行车
  • 乘坐在正在行驶的汽车、巴士或火车内

不会触发大幅度动作传感器的情况示例如下:

  • 手机放在口袋里,人不动
  • 手机放在桌子上,而桌子由于附近的交通情况或洗衣机运转而轻微振动

从更高层面来看,大幅度动作传感器可用于降低位置测定的功耗。当定位算法检测到设备静止时,可将设备切换到低功耗模式,在该模式下,这些算法依赖用户改变位置时发生的大幅度动作来唤醒设备。

该传感器必须具备低功耗特性。这样可以节省功耗,但可能会导致少量漏报情况。这样做是出于以下几个原因:

  • 该传感器的目标是节省电量。
  • 用户不动时触发事件(误报)会消耗大量电量,因此应尽量加以避免。
  • 在用户移动时不触发事件(漏报)是可以接受的,只要不频繁出现这种情况即可。如果用户已经行走 10 秒钟,但这 10 秒内一直未触发事件,则是不可接受的。

每个传感器事件在 sensors_event_t.data[0] 中报告 1

3.3 步测器

底层物理传感器:加速度计(可能还有其他低功耗计量器)

报告模式:特殊模式(一步触发一个事件)

低功耗

getDefaultSensor(SENSOR_TYPE_STEP_DETECTOR) 返回非唤醒传感器

用户每走一步,步测器就触发一个事件。

sensors_event_t.timestamp 事件的时间戳对应脚部触地的时刻,此时会产生较大的加速度变化。

与计步器相比,步测器的延迟较低(小于两秒)。步测器和计步器都可以在用户步行、奔跑和走楼梯时进行感测。当用户骑自行车、驾车或乘坐其他交通工具时,不应触发感测。

该传感器必须具备低功耗特性。也就是说,如果在硬件中无法完成步数感测,则不应定义此传感器。尤其是,当启用步测器但未启用加速度计时,只有步数(而非每次加速度计读取)会触发中断。

sampling_period_ns 对步测器没有影响。

每个传感器事件在 sensors_event_t.data[0] 中报告 1

3.4 计步器

底层物理传感器:加速度计(可能还有其他低功耗计量器)

报告模式:变化时触发模式

低功耗

getDefaultSensor(SENSOR_TYPE_STEP_COUNTER) 返回非唤醒传感器

计步器报告自激活后上一次重新启动以来用户行走的步数。

测量结果在 sensors_event_t.step_counter 中以 uint64_t 报告,并仅在系统重新启动时重置为零。

事件的时间戳设置为该事件最后一次迈步的时间。

请参阅步测器传感器类型,了解一步所对应的时间的意义。

与步测器相比,计步器可能具有更高的延迟(最多 10 秒)。也正因这种延迟,该传感器具备较高的准确性;完成一整天的测量后,步数应在实际步数的 10% 偏差范围内。步测器和计步器都可以在用户步行、奔跑和走楼梯时进行感测。当用户骑自行车、驾车或乘坐其他交通工具时,不应触发感测。

硬件必须确保内部步数始终不会溢出。硬件内部计数器的大小下限应为 16 位。在即将发生溢出时(最多约每 2^16 步一次),可以唤醒 SoC,以便驱动程序可进行计数器维护。

正如互动传感器中所述,当该传感器工作时,不得干扰任何其他传感器,特别是很可能正在使用中的加速度计。

如果特定设备不支持这些操作模式,则 HAL 不得报告该传感器类型。也就是说,不能在 HAL 中“模拟”该传感器。

该传感器必须具备低功耗特性。也就是说,如果在硬件中无法完成步数感测,则不应定义此传感器。尤其是,当启用计步器但未启用加速度计时,只有步数(而非加速度计数据)会触发中断。

3.5 倾斜检测器

底层物理传感器:加速度计(可能还有其他低功耗计量器)

报告模式:特殊模式

低功耗

仅实现该传感器的唤醒版本。

getDefaultSensor(SENSOR_TYPE_TILT_DETECTOR) 返回唤醒传感器

每次检测到倾斜事件时,倾斜检测器会生成一个事件。

倾斜事件定义如下:自激活或自传感器生成的最后一次事件起,2 秒时隙内平均重力加速度方向变化至少 35 度。算法如下:

  • reference_estimated_gravity = 激活后的第一秒内加速度计的平均测量值或生成最后一次倾斜事件时的估算重力。
  • current_estimated_gravity = 过去 2 秒内加速度计的平均测量值。
  • 触发条件为 angle(reference_estimated_gravity, current_estimated_gravity) > 35 degrees

当加速度较大而手机方向未发生改变时,不应触发倾斜事件。例如,驾驶汽车时急转弯或猛烈加速不应触发倾斜事件,即使平均加速度的角度变化可能超过 35 度亦如此。通常情况下,只需借助加速度计就能实现该传感器。也可以使用其他传感器(如果功耗增加不明显的话)。这是一个低功耗传感器,应允许 SoC 进入挂起模式。请勿在 HAL 中模拟此传感器。每个传感器事件在 sensors_event_t.data[0] 中报告 1

4.姿势复合传感器

4.1 旋转矢量传感器

4.1.1 定义

底层物理传感器:加速度计、磁力计和陀螺仪

报告模式:连续模式

getDefaultSensor(SENSOR_TYPE_ROTATION_VECTOR) 返回非唤醒传感器

旋转矢量传感器可报告设备相对于东北天坐标系的方向。通常通过集成加速度计、陀螺仪和磁力计的读数获得该值。东北上坐标系是指完全正交基,其中:

  • X 轴指向东,与地面相切。
  • Y 轴指向北,与地面相切。
  • Z 轴指向上,与地面垂直。

手机方向表示为东北天坐标系与手机坐标系对齐所需的旋转幅度。也就是说,对世界坐标系 (X,Y,Z) 应用这一幅度的旋转将使该坐标系与手机坐标系 (x,y,z) 对齐。

该旋转可看作围绕轴 rot_axis 将手机旋转 θ 角度,从参照(与东北天对齐)设备方向转到当前设备方向。该旋转被编码为一个单位四元数的四个无量纲 x、y、z、w 分量:

  • sensors_event_t.data[0] = rot_axis.x*sin(theta/2)
  • sensors_event_t.data[1] = rot_axis.y*sin(theta/2)
  • sensors_event_t.data[2] = rot_axis.z*sin(theta/2)
  • sensors_event_t.data[3] = cos(theta/2)

其中:

  • rot_axis 的 x、y 和 z 字段是表示旋转轴的单位长度向量的东北天坐标
  • theta 是旋转角度

四元数是一个单位四元数:其范数必须为 1。 不满足此要求将导致客户端行为不稳定。

此外,该传感器会报告估算的首向精度:

sensors_event_t.data[4] = estimated_accuracy(以弧度为单位)

在 95% 的时间里,首向误差必须小于 estimated_accuracy。该传感器必须使用陀螺仪作为主要方向变化输入源。

该传感器还使用加速度计和磁力计输入源来弥补陀螺仪偏移,但不能仅使用加速度计和磁力计来实现该传感器。

旋转矢量传感器简称RV-sensor。

旋转矢量代表设备的方向,是一个将坐标轴和角度混合计算得到的数据。

RV-sensor输出三个数据:

xsin(theta/2) ysin(theta/2) z*sin(theta/2)

sin(theta/2)是RV的数量级。

RV的方向与轴旋转的方向相同。

RV的三个数值,与cos(theta/2)组成一个四元组。

RV的数据没有单位,使用的坐标系与加速度相同。

举例:

sensors_event_t.data[0] = xsin(theta/2) sensors_event_t.data[1] = ysin(theta/2) sensors_event_t.data[2] = z*sin(theta/2) sensors_event_t.data[3] = cos(theta/2)

GV、LA和RV的数值没有物理传感器可以直接给出,需要G-sensor、O-sensor和Gyro-sensor经过算法计算后得出。

4.1.2 基本使用

旋转矢量将设备的屏幕方向表示为角度和轴的组合,其中设备已围绕轴(x、y 或 z)旋转了 θ 度。以下代码展示如何获取默认旋转矢量传感器的实例:

private SensorManager sensorManager;
private Sensor sensor;
...
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR);

旋转矢量的三个元素表示如下:

xsin(θ/2)、ysin(θ/2)、z*sin(θ/2)

其中旋转矢量的大小等于 sin(θ/2),并且旋转矢量的方向等于旋转轴的方向。

4.2 游戏旋转矢量传感器

底层物理传感器:加速度计和陀螺仪(无磁力计)

报告模式:连续模式

getDefaultSensor(SENSOR_TYPE_GAME_ROTATION_VECTOR) 返回非唤醒传感器

游戏旋转矢量传感器类似于旋转矢量传感器,但不使用地磁场。因此,Y 轴不指向北,而是指向其他参照坐标。该参考坐标可以偏移与陀螺仪沿 Z 轴偏移时的幅度相同数量级的幅度。

请参阅旋转矢量传感器,详细了解如何设置 sensors_event_t.data[0-3]。此传感器不报告估算的首向精度:保留 sensors_event_t.data[4],并且应将其设置为 0。理想情况下,经过旋转并返回到与现实世界方向同向的手机应该报告相同的游戏旋转矢量。该传感器必须基于陀螺仪和加速度计。不能使用磁力计作为输入源,也不可通过估算陀螺仪偏差间接作为输入源。

4.3 重力传感器

底层物理传感器:加速度计和(如有)陀螺仪(或如果陀螺仪不存在,则使用磁力计)

报告模式:连续模式

getDefaultSensor(SENSOR_TYPE_GRAVITY) 返回非唤醒传感器

重力传感器可报告设备坐标系中重力的方向和大小。

重力矢量分量在 sensors_event_t.acceleration、x、y 和 z 字段中报告(以 m/s^2 为单位)。

当设备静止时,重力传感器的输出结果应与加速度计的输出结果相同。在地球上,重力加速度约为 9.8 m/s^2。

如果设备具有陀螺仪,则重力传感器必须使用陀螺仪和加速度计作为输入源。

如果设备不具有陀螺仪,则重力传感器必须使用加速度计和磁力计作为输入源。

4.4 地磁旋转矢量传感器

底层物理传感器:加速度计和磁力计(无陀螺仪)

报告模式:连续模式

低功耗

getDefaultSensor(SENSOR_TYPE_GEOMAGNETIC_ROTATION_VECTOR) 返回非唤醒传感器

地磁旋转矢量传感器与旋转矢量传感器类似,但它使用磁力计而不是陀螺仪。

该传感器必须基于磁力计。它不能使用陀螺仪来实现,并且不能使用陀螺仪输入。

请参阅旋转矢量传感器,详细了解如何设置 sensors_event_t.data[0-4]

与旋转矢量传感器类似,在 95% 的时间里,首向误差必须小于估算精度 (sensors_event_t.data[4])。

该传感器必须具备低功耗特性,因此必须在硬件中实现。