运动传感器
2023-10-07 20:00:46发布 浏览529次 信息编号:77529
友情提醒:凡是以各种理由向你收取费用,均有骗子嫌疑,请提高警惕,不要轻易支付。
运动传感器
该平台提供各种传感器,可让您监控设备的移动。
传感器的可能架构因传感器类型而异:
大多数设备都有加速计,现在许多设备也有陀螺仪。 基于软件的传感器的可用性变化较大,因为它们通常依赖一个或多个硬件传感器来获取数据。 根据设备的不同,这些基于软件的传感器可以从加速度计、磁力计或陀螺仪获取数据。
运动传感器可用于监控设备运动,例如倾斜、摇动、旋转或摆动。 移动通常反映用户的直接输入(例如,用户在游戏中驾驶汽车,或在游戏中控制球),但也可能反映设备所在的物理环境(例如,移动开车时与您在一起)。 在第一种情况下,您正在监视相对于设备参考系或应用程序参考系的运动; 在第二种情况下,您正在监视相对于世界参考系的运动。 运动传感器本身通常不用于监视设备位置,但可以与其他传感器(例如地磁场传感器)一起使用,以确定设备相对于世界参考系的位置(有关更多信息,请参阅位置传感器)。
所有运动传感器都返回每个传感器值的多维数组。 例如,在单个传感器事件期间,加速计返回三个轴上的加速力数据,而陀螺仪返回三个轴上的旋转速率数据。 这些数据值与其他参数一起以 float array() 形式返回。 表 1 总结了平台上可用的运动传感器。
表 1. 平台支持的运动传感器。
传感器 传感器事件数据 描述 测量单位
.[0]
沿 x 轴的加速力(包括重力)。
米/秒2
.[1]
沿 y 轴的加速力(包括重力)。
.[2]
沿 z 轴的加速力(包括重力)。
.[0]
沿 X 轴测量的加速度,没有任何偏移补偿。
米/秒2
.[1]
沿 Y 轴测量的加速度,没有任何偏移补偿。
.[2]
沿 Z 轴测量的加速度,没有任何偏移补偿。
.[3]
使用估计的偏移补偿沿 X 轴测量的加速度。
.[4]
使用估计的偏移补偿沿 Y 轴测量的加速度。
.[5]
使用估计的偏移补偿沿 Z 轴测量的加速度。
.[0]
沿 x 轴的重力。
米/秒2
.[1]
沿 y 轴的重力。
.[2]
沿 z 轴的重力。
.[0]
绕 x 轴的旋转速率。
弧度/秒
.[1]
绕 y 轴的旋转速率。
.[2]
绕 z 轴的旋转速率。
.[0]
绕 x 轴的旋转速率(无漂移补偿)。
弧度/秒
.[1]
绕 y 轴的旋转速率(无漂移补偿)。
.[2]
绕 z 轴的旋转速率(无漂移补偿)。
.[3]
绕 x 轴的估计漂移。
.[4]
绕 y 轴的估计漂移。
.[5]
绕 z 轴的估计漂移。
.[0]
沿 x 轴的加速力(不包括重力)。
米/秒2
.[1]
沿 y 轴的加速力(不包括重力)。
.[2]
沿 z 轴的加速力(不包括重力)。
.[0]
沿 x 轴的旋转矢量分量 (x * sin(θ/2))。
无单位
.[1]
沿 y 轴的旋转矢量分量 (y * sin(θ/2))。
.[2]
沿 z 轴的旋转矢量分量 (z * sin(θ/2))。
.[3]
旋转矢量的标量分量 ((cos(θ/2)).1
不适用
不适用
不适用
.[0]
自上次重新启动激活的传感器以来用户所采取的步数。
步数
不适用
不适用
不适用
1 标量分量是可选值。
旋转矢量传感器和重力传感器是最常用的运动检测和监控传感器。 旋转矢量传感器用途极其广泛,可用于各种与运动相关的任务,例如检测手势、监视角度变化以及监视相对屏幕方向的变化。 例如,如果您正在开发游戏、增强现实应用程序、2D 或 3D 指南针或相机稳定应用程序,旋转矢量传感器是理想的选择。 在大多数情况下,使用这些传感器比使用加速度计和地磁场传感器或方向传感器更好。
开源项目传感器
开源项目(AOSP)提供了以下三种基于软件的运动传感器:重力传感器、线性加速度传感器和旋转矢量传感器。 这些传感器已在 4.0 中更新,现在使用设备的陀螺仪(以及其他传感器)来提高稳定性和性能。 如果你想尝试这些传感器,你可以使用和(供应商是LLC;版本号是3)来识别它们。 您必须按供应商和版本号识别这些传感器,因为系统将这三个传感器视为辅助传感器。 例如,如果设备制造商提供自己的重力传感器,则 AOSP 重力传感器将显示为辅助重力传感器。 所有三个传感器都依赖于陀螺仪:如果设备没有陀螺仪,这些传感器将不会显示并且无法工作。
使用重力传感器
重力传感器提供指示重力方向和大小的三维矢量。 通常,该传感器用于确定设备在空间中的相对屏幕方向。 以下代码展示了如何获取默认重力传感器的实例:
val sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager val sensor: Sensor? = sensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY)
爪哇
private SensorManager sensorManager; private Sensor sensor; ... sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); sensor = sensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY);
单位与加速度传感器使用的单位相同(m/s2),坐标系与加速度传感器使用的坐标系相同。
注意:当设备静止时,重力传感器的输出应与加速度计的输出相同。
使用线性加速度计
线性加速度传感器为您提供一个三维矢量,表示沿每个设备轴(不包括重力)的加速度。 您可以使用该值来执行手势检测。 该值还可以用作使用航位推算的惯性导航系统的输入。 以下代码展示了如何获取默认线性加速度传感器的实例:
val sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager val sensor: Sensor? = sensorManager.getDefaultSensor(Sensor.TYPE_LINEAR_ACCELERATION)
爪哇
private SensorManager sensorManager; private Sensor sensor; ... sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); sensor = sensorManager.getDefaultSensor(Sensor.TYPE_LINEAR_ACCELERATION);
从概念上讲,该传感器根据以下关系为您提供加速度数据:
linear acceleration = acceleration - acceleration due to gravity
当您想要获得独立于重力的加速度数据时,通常使用此传感器。 例如,您可以使用此传感器来查看您的汽车行驶的速度。 线性加速度传感器始终存在需要消除的偏移。 最简单的方法是在您的应用程序中构建校准步骤。 在校准过程中,您可以要求用户将设备放置在桌子上并读取所有三个轴的偏移量。 然后,您可以从加速度传感器的直接读数中减去该偏移,以获得实际的线性加速度。
传感器和加速度传感器使用的坐标系相同,测量单位(m/s2)也相同。使用旋转矢量传感器
旋转矢量将设备的屏幕方向表示为角度和设备围绕其旋转 θ 度的轴的组合。 以下代码显示如何获取默认旋转矢量传感器的实例:
val sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager val sensor: Sensor? = sensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR)
爪哇
private SensorManager sensorManager; private Sensor sensor; ... sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR);
旋转向量的三个元素表示如下:
旋转矢量的大小等于sin(θ/2),旋转矢量的方向等于旋转轴的方向。
表 1. 旋转矢量传感器使用的坐标系。
旋转向量的三个元素等于单位四元数的后三个(cos(θ/2), x*sin(θ/2), y*sin(θ/2), z*sin(θ/2) )) 部分。 旋转矢量的元素没有单位。 x、y 和 z 轴的定义方式与加速度传感器相同。 参考坐标系定义为直接正交基(见图 1)。 该坐标系具有以下特点:
请参阅 .java 以获取演示如何使用旋转矢量传感器的示例应用程序。
使用有效的运动传感器
每次检测到有效运动时,有效运动传感器都会触发一个事件,然后将其禁用。 有效运动是可能导致用户位置发生变化的运动; 例如步行、骑自行车或坐在移动的车辆中。 以下代码显示如何获取默认活动运动传感器的实例以及如何注册事件侦听器:
val sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
val mSensor: Sensor? = sensorManager.getDefaultSensor(Sensor.TYPE_SIGNIFICANT_MOTION)
val triggerEventListener = object : TriggerEventListener() {
override fun onTrigger(event: TriggerEvent?) {
// Do work
}
}
mSensor?.also { sensor ->
sensorManager.requestTriggerSensor(triggerEventListener, sensor)
}
爪哇
private SensorManager sensorManager;
private Sensor sensor;
private TriggerEventListener triggerEventListener;
...
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
sensor = sensorManager.getDefaultSensor(Sensor.TYPE_SIGNIFICANT_MOTION);
triggerEventListener = new TriggerEventListener() {
@Override
public void onTrigger(TriggerEvent event) {
// Do work
}
};
sensorManager.requestTriggerSensor(triggerEventListener, mSensor);
详情请参阅。
使用计步器传感器
计步器传感器提供自激活传感器后上次重新启动以来用户已采取的步数。 计步器的延迟时间较长(最多 10 秒),但比计步器传感器更准确。
注意:您必须声明您的应用程序的权限,才能在运行(API 级别 29)或更高版本的设备上使用此传感器。
以下代码显示如何获取默认计步器传感器的实例:
val sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager val sensor: Sensor? = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER)
爪哇
private SensorManager sensorManager; private Sensor sensor; ... sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); sensor = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER);
为了保护运行应用程序的设备上的电池,您应该使用一个类以特定的时间间隔从计步器传感器检索当前值。 尽管不同类型的应用需要不同的传感器读取间隔,但除非您的应用需要来自传感器的实时数据,否则该间隔应尽可能长。
使用计步器传感器
每当用户迈出一步,计步器传感器就会触发一个事件。 延迟预计低于 2 秒。
注意:您必须声明您的应用程序的权限,才能在运行(API 级别 29)或更高版本的设备上使用此传感器。
以下代码显示如何获取默认起搏器传感器的实例:
val sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager val sensor: Sensor? = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_DETECTOR)
爪哇
private SensorManager sensorManager; private Sensor sensor; ... sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); sensor = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_DETECTOR);
使用原始数据
以下传感器为您的应用程序提供有关施加到设备的线性力和旋转力的原始数据。 为了有效地使用这些传感器的值,您需要过滤掉环境中的重力等因素。 您可能还想对值趋势应用平滑算法以减少噪音。
使用加速度计
加速度传感器测量施加到设备上的加速度,包括重力。 以下代码展示了如何获取默认加速度传感器的实例:
val sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager val sensor: Sensor? = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)
爪哇
private SensorManager sensorManager; private Sensor sensor; ... sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
从概念上讲,加速度传感器通过使用以下关系测量施加到传感器本身的力 (Fs) 来确定施加到设备的加速度 (Ad):
然而,重力总是根据以下关系影响测量的加速度:
因此,当设备放在桌子上(未加速)时,加速度计读数为 g = 9.81 m/s2。 同样,当设备自由落体并因此以 9.81 m/s2 快速向地面加速时,其加速度计读数为 g = 0 m/s2。 因此,为了测量设备的实际加速度,必须从加速度计数据中消除重力的影响。 这可以通过应用高通滤波器来实现。 相反,您可以使用低通滤波器来隔离重力。 以下示例展示了如何执行此操作:
override fun onSensorChanged(event: SensorEvent) {
// In this example, alpha is calculated as t / (t + dT),
// where t is the low-pass filter's time-constant and
// dT is the event delivery rate.
val alpha: Float = 0.8f
// Isolate the force of gravity with the low-pass filter.
gravity[0] = alpha * gravity[0] + (1 - alpha) * event.values[0]
gravity[1] = alpha * gravity[1] + (1 - alpha) * event.values[1]
gravity[2] = alpha * gravity[2] + (1 - alpha) * event.values[2]
// Remove the gravity contribution with the high-pass filter.
linear_acceleration[0] = event.values[0] - gravity[0]
linear_acceleration[1] = event.values[1] - gravity[1]
linear_acceleration[2] = event.values[2] - gravity[2]
}
爪哇
public void onSensorChanged(SensorEvent event){
// In this example, alpha is calculated as t / (t + dT),
// where t is the low-pass filter's time-constant and
// dT is the event delivery rate.
final float alpha = 0.8;
// Isolate the force of gravity with the low-pass filter.
gravity[0] = alpha * gravity[0] + (1 - alpha) * event.values[0];
gravity[1] = alpha * gravity[1] + (1 - alpha) * event.values[1];
gravity[2] = alpha * gravity[2] + (1 - alpha) * event.values[2];
// Remove the gravity contribution with the high-pass filter.
linear_acceleration[0] = event.values[0] - gravity[0];
linear_acceleration[1] = event.values[1] - gravity[1];
linear_acceleration[2] = event.values[2] - gravity[2];
}
注意:您可以使用许多不同的技术来过滤传感器数据。 上面的代码示例使用简单的滤波器常数 (alpha) 来创建低通滤波器。 该滤波器常数源自时间常数 (t),该时间常数粗略地表示滤波器添加到传感器事件的延迟以及传感器的事件传输速率 (dt)。 此代码示例演示如何使用 alpha 值 0.8。 如果您使用此过滤方法,您可能需要选择不同的 alpha 值。
加速度计使用标准传感器。 实际上,这意味着当设备以其自然屏幕方向平放在桌子上时,适用以下条件:
一般来说,如果您想监控设备的运动,加速度计是一个很好的传感器。 几乎所有正在运行的手机和平板电脑都配有加速计,其功耗比其他运动传感器低约 10 倍。 一个缺点是您可能必须实施低通和高通滤波器来消除重力并减少噪音。
SDK 提供了一个示例应用程序,展示如何使用加速度传感器 (Play)。
使用陀螺仪
陀螺仪测量绕设备 x、y 和 z 轴的旋转速率(弧度/秒)。 以下代码展示了如何获取默认陀螺仪的实例:
val sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager val sensor: Sensor? = sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE)
爪哇
private SensorManager sensorManager; private Sensor sensor; ... sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); sensor = sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);
传感器的坐标系与加速度传感器所使用的坐标系相同。 逆时针旋转为正; 也就是说,如果观察者从 x、y 或 z 轴的正位置观察原点处的设备,则该设备对于观察者来说似乎是逆时针旋转。 将报告正旋转。 这是向前旋转的标准数学定义,与方向传感器使用的滚动定义不同。
通常,陀螺仪的输出随时间进行积分,以计算描述角度随时间步长变化的旋转。 例如:
// Create a constant to convert nanoseconds to seconds.
private val NS2S = 1.0f / 1000000000.0f
private val deltaRotationVector = FloatArray(4) { 0f }
private var timestamp: Float = 0f
override fun onSensorChanged(event: SensorEvent?) {
// This timestep's delta rotation to be multiplied by the current rotation
// after computing it from the gyro sample data.
if (timestamp != 0f && event != null) {
val dT = (event.timestamp - timestamp) * NS2S
// Axis of the rotation sample, not normalized yet.
var axisX: Float = event.values[0]
var axisY: Float = event.values[1]
var axisZ: Float = event.values[2]
// Calculate the angular speed of the sample
val omegaMagnitude: Float = sqrt(axisX * axisX + axisY * axisY + axisZ * axisZ)
// Normalize the rotation vector if it's big enough to get the axis
// (that is, EPSILON should represent your maximum allowable margin of error)
if (omegaMagnitude > EPSILON) {
axisX /= omegaMagnitude
axisY /= omegaMagnitude
axisZ /= omegaMagnitude
}
// Integrate around this axis with the angular speed by the timestep
// in order to get a delta rotation from this sample over the timestep
// We will convert this axis-angle representation of the delta rotation
// into a quaternion before turning it into the rotation matrix.
val thetaOverTwo: Float = omegaMagnitude * dT / 2.0f
val sinThetaOverTwo: Float = sin(thetaOverTwo)
val cosThetaOverTwo: Float = cos(thetaOverTwo)
deltaRotationVector[0] = sinThetaOverTwo * axisX
deltaRotationVector[1] = sinThetaOverTwo * axisY
deltaRotationVector[2] = sinThetaOverTwo * axisZ
deltaRotationVector[3] = cosThetaOverTwo
}
timestamp = event?.timestamp?.toFloat() ?: 0f
val deltaRotationMatrix = FloatArray(9) { 0f }
SensorManager.getRotationMatrixFromVector(deltaRotationMatrix, deltaRotationVector);
// User code should concatenate the delta rotation we computed with the current rotation
// in order to get the updated rotation.
// rotationCurrent = rotationCurrent * deltaRotationMatrix;
}
爪哇
// Create a constant to convert nanoseconds to seconds.
private static final float NS2S = 1.0f / 1000000000.0f;
private final float[] deltaRotationVector = new float[4]();
private float timestamp;
public void onSensorChanged(SensorEvent event) {
// This timestep's delta rotation to be multiplied by the current rotation
// after computing it from the gyro sample data.
if (timestamp != 0) {
final float dT = (event.timestamp - timestamp) * NS2S;
// Axis of the rotation sample, not normalized yet.
float axisX = event.values[0];
float axisY = event.values[1];
float axisZ = event.values[2];
// Calculate the angular speed of the sample
float omegaMagnitude = sqrt(axisX*axisX + axisY*axisY + axisZ*axisZ);
// Normalize the rotation vector if it's big enough to get the axis
// (that is, EPSILON should represent your maximum allowable margin of error)
if (omegaMagnitude > EPSILON) {
axisX /= omegaMagnitude;
axisY /= omegaMagnitude;
axisZ /= omegaMagnitude;
}
// Integrate around this axis with the angular speed by the timestep
// in order to get a delta rotation from this sample over the timestep
// We will convert this axis-angle representation of the delta rotation
// into a quaternion before turning it into the rotation matrix.
float thetaOverTwo = omegaMagnitude * dT / 2.0f;
float sinThetaOverTwo = sin(thetaOverTwo);
float cosThetaOverTwo = cos(thetaOverTwo);
deltaRotationVector[0] = sinThetaOverTwo * axisX;
deltaRotationVector[1] = sinThetaOverTwo * axisY;
deltaRotationVector[2] = sinThetaOverTwo * axisZ;
deltaRotationVector[3] = cosThetaOverTwo;
}
timestamp = event.timestamp;
float[] deltaRotationMatrix = new float[9];
SensorManager.getRotationMatrixFromVector(deltaRotationMatrix, deltaRotationVector);
// User code should concatenate the delta rotation we computed with the current rotation
// in order to get the updated rotation.
// rotationCurrent = rotationCurrent * deltaRotationMatrix;
}
标准陀螺仪提供原始旋转数据,无需对噪声和漂移(偏差)进行任何过滤或校正。 实际上,陀螺仪噪声和漂移可能会引入需要补偿的误差。 通常,您可以通过监视其他传感器(例如重力传感器或加速度计)来确定漂移(偏差)和噪声。
使用未经校准的陀螺仪
未校准的陀螺仪类似,只是没有对旋转速率应用陀螺仪漂移补偿。 工厂校准和温度补偿仍然适用于旋转速率。 未校准的陀螺仪可用于后处理和融合屏幕方向数据。 通常,.[0] 将接近 .[0] - .[3]。 现在,
〜= -
注意:未校准的传感器提供更多原始结果,并且可能包含一些偏差,但其测量结果包含从应用校正到校准的较少跳跃。 某些应用程序可能更喜欢这些未校准的结果,因为它们更平滑且更可靠。 例如,如果应用程序尝试进行自己的传感器融合,引入校准实际上可能会扭曲结果。
除了旋转速率之外,未校准的陀螺仪还提供绕每个轴的估计漂移。 以下代码显示如何获取默认未校准陀螺仪的实例:
val sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager val sensor: Sensor? = sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE_UNCALIBRATED)
爪哇
private SensorManager sensorManager; private Sensor sensor; ... sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); sensor = sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE_UNCALIBRATED);
其他代码示例
示例和示例进一步演示了本页所涵盖的 API 的使用。
另请阅读
提醒:请联系我时一定说明是从星空网上看到的!