Android: 如何同步多个IMU传感器(Accelerometer/Gyroscope/Magnetic)?
Android: how to synchronise multiple IMU sensors(Accelerometer/Gyroscope/Magnetic)?
我目前正在开发一个 android 应用程序,该应用程序收集用于定位的 IMU 数据(加速度计、陀螺仪和磁场),这需要非常高的测量时间精度。所有三个传感器都设置为 SENSOR.DELAY.FASTEST,这是我的代码。
@Override
public void onSensorChanged(SensorEvent sensorEvent) {
final float alpha = 0.97f;
//in milliseconds since last boot
time = SystemClock.elapsedRealtime();
switch (sensorEvent.sensor.getType()){
case Sensor.TYPE_ACCELEROMETER:
Log.d(TAG,"TYPE_ACCELEROMETER: "+sensorEvent.timestamp);
//System.arraycopy(sensorEvent.values,0,LastAccReading,0,sensorEvent.values.length);
LastAccReading[0] = alpha * LastAccReading[0] + (1-alpha) * sensorEvent.values[0];
LastAccReading[1] = alpha * LastAccReading[1] + (1-alpha) * sensorEvent.values[1];
LastAccReading[2] = alpha * LastAccReading[2] + (1-alpha) * sensorEvent.values[2];
break;
case Sensor.TYPE_MAGNETIC_FIELD:
Log.d(TAG,"TYPE_MAGNETIC_FIELD: "+sensorEvent.timestamp);
//System.arraycopy(sensorEvent.values,0,LastMagReading,0,sensorEvent.values.length);
LastMagReading[0] = alpha * LastMagReading[0] + (1-alpha) * sensorEvent.values[0];
LastMagReading[1] = alpha * LastMagReading[1] + (1-alpha) * sensorEvent.values[1];
LastMagReading[2] = alpha * LastMagReading[2] + (1-alpha) * sensorEvent.values[2];
break;
case Sensor.TYPE_GYROSCOPE:
Log.d(TAG,"TYPE_GYROSCOPE: "+sensorEvent.timestamp);
LastGyroReading[0] = sensorEvent.values[0];
LastGyroReading[1] = sensorEvent.values[1];
LastGyroReading[2] = sensorEvent.values[2];
}
// Rotation matrix based on current readings from accelerometer and magnetometer.
SensorManager.getRotationMatrix(rotationMatrix, inclinationMatrix,
LastAccReading, LastMagReading);
// Express the updated rotation matrix as three orientation angles.
SensorManager.getOrientation(rotationMatrix, orientationAngles);
//Log.i("OrientationTestActivity",String.format("Orientation: %f, %f, %f", orientationAngles[0], orientationAngles[1], orientationAngles[2]));
}
通过查看 sensorEvent.timestamp
enter image description here
我可以看到加速度计和陀螺仪在 420Hz 左右具有相同的采样率,而磁场在 100Hz 左右要慢得多。并且加速度计和陀螺仪不会同时返回传感器值,这意味着在某个时间戳,三个传感器值中只有一个有效,另外两个会有几毫秒的时间偏移。
我能做些什么吗?提前致谢。
消费者传感器不是最准确的,并且会受到噪声和漂移的影响(查看任何 IMU 数据表以了解详细信息)。对于常见用例,它们足够准确。
任何基于 Android 的传感器至少需要符合 Android Compatibility Definition Document section on Sensors。
由于设备中的传感器不是一个新主题,观看这个关于传感器融合的旧 Google 会谈视频可能会有所帮助:Sensor Fusion on Android Devices: A Revolution in Motion Processing
虽然您可能担心不同的时间戳,但我相信您想要的精度水平是不现实的,因为传感器具有噪声容限并且会漂移到它们的值。
至于开发人员在给定现有误差范围的情况下所做的事情,假设用例是人体运动,传感器数据通常会随时间 and/or 通过 low-pass 过滤器进行平均。对于大多数用例来说,这已经足够了,但正如 this article on ARCore and ARKit 中所述,在那些支持 AR 的设备上,认证这些设备中的传感器将需要更严格(且成本最高)的校准。
那些尝试 VR/AR 类型行为的人可能正在使用
SensorDirectChannel but be aware of the stated rate variance and hardware/OS limitations.
我目前正在开发一个 android 应用程序,该应用程序收集用于定位的 IMU 数据(加速度计、陀螺仪和磁场),这需要非常高的测量时间精度。所有三个传感器都设置为 SENSOR.DELAY.FASTEST,这是我的代码。
@Override
public void onSensorChanged(SensorEvent sensorEvent) {
final float alpha = 0.97f;
//in milliseconds since last boot
time = SystemClock.elapsedRealtime();
switch (sensorEvent.sensor.getType()){
case Sensor.TYPE_ACCELEROMETER:
Log.d(TAG,"TYPE_ACCELEROMETER: "+sensorEvent.timestamp);
//System.arraycopy(sensorEvent.values,0,LastAccReading,0,sensorEvent.values.length);
LastAccReading[0] = alpha * LastAccReading[0] + (1-alpha) * sensorEvent.values[0];
LastAccReading[1] = alpha * LastAccReading[1] + (1-alpha) * sensorEvent.values[1];
LastAccReading[2] = alpha * LastAccReading[2] + (1-alpha) * sensorEvent.values[2];
break;
case Sensor.TYPE_MAGNETIC_FIELD:
Log.d(TAG,"TYPE_MAGNETIC_FIELD: "+sensorEvent.timestamp);
//System.arraycopy(sensorEvent.values,0,LastMagReading,0,sensorEvent.values.length);
LastMagReading[0] = alpha * LastMagReading[0] + (1-alpha) * sensorEvent.values[0];
LastMagReading[1] = alpha * LastMagReading[1] + (1-alpha) * sensorEvent.values[1];
LastMagReading[2] = alpha * LastMagReading[2] + (1-alpha) * sensorEvent.values[2];
break;
case Sensor.TYPE_GYROSCOPE:
Log.d(TAG,"TYPE_GYROSCOPE: "+sensorEvent.timestamp);
LastGyroReading[0] = sensorEvent.values[0];
LastGyroReading[1] = sensorEvent.values[1];
LastGyroReading[2] = sensorEvent.values[2];
}
// Rotation matrix based on current readings from accelerometer and magnetometer.
SensorManager.getRotationMatrix(rotationMatrix, inclinationMatrix,
LastAccReading, LastMagReading);
// Express the updated rotation matrix as three orientation angles.
SensorManager.getOrientation(rotationMatrix, orientationAngles);
//Log.i("OrientationTestActivity",String.format("Orientation: %f, %f, %f", orientationAngles[0], orientationAngles[1], orientationAngles[2]));
}
通过查看 sensorEvent.timestamp enter image description here 我可以看到加速度计和陀螺仪在 420Hz 左右具有相同的采样率,而磁场在 100Hz 左右要慢得多。并且加速度计和陀螺仪不会同时返回传感器值,这意味着在某个时间戳,三个传感器值中只有一个有效,另外两个会有几毫秒的时间偏移。
我能做些什么吗?提前致谢。
消费者传感器不是最准确的,并且会受到噪声和漂移的影响(查看任何 IMU 数据表以了解详细信息)。对于常见用例,它们足够准确。
任何基于 Android 的传感器至少需要符合 Android Compatibility Definition Document section on Sensors。
由于设备中的传感器不是一个新主题,观看这个关于传感器融合的旧 Google 会谈视频可能会有所帮助:Sensor Fusion on Android Devices: A Revolution in Motion Processing
虽然您可能担心不同的时间戳,但我相信您想要的精度水平是不现实的,因为传感器具有噪声容限并且会漂移到它们的值。
至于开发人员在给定现有误差范围的情况下所做的事情,假设用例是人体运动,传感器数据通常会随时间 and/or 通过 low-pass 过滤器进行平均。对于大多数用例来说,这已经足够了,但正如 this article on ARCore and ARKit 中所述,在那些支持 AR 的设备上,认证这些设备中的传感器将需要更严格(且成本最高)的校准。
那些尝试 VR/AR 类型行为的人可能正在使用 SensorDirectChannel but be aware of the stated rate variance and hardware/OS limitations.