我可能可以通过将加速度计与陀螺仪结合起来获得这些值,但我不知道如何用陀螺仪的值偏移加速度计的值。
这是否可能,如果可能,如何实现?
除非您重新定义问题,否则无法实现您所描述的内容。为了帮助您重新定义问题,我将概述以下主要问题:
首先,我猜想您所说的“绝对加速度”是指相对于地理参考的加速度。仅凭加速度计无法实现这一点,因为它对地理参考没有任何了解。如果您移动足够远以获得GPS信号,或者使用指南针,可能可以解决这个问题,但每种方法都有其自身的问题(尽管至少这个问题是可解决的)。
第二个问题是,重力和加速度在加速度计单独使用时完全无法区分(这被称为“等效原理”)。 因此,任何测量到的加速度始终是重力和加速度的矢量和,但这些方程式总有多个解,而在加速度小于重力的常见情况下,您真的无法确定关于加速度的任何信息。 由于重力略微恒定,因此也有办法解决这个问题,例如使用陀螺仪,或者您的用户可以保持手机固定方向(例如,通过看外部线索如地平线),这两种方法中的任何一种都可能让您减去重力的影响,但它通常是一个非平凡的问题。
最后一点需要注意的是,您似乎在思考以地球为基准的坐标系,但手机的加速度计仅适用于手机固定的坐标系。也就是说,加速度计的z轴可能与地球上下无关,而与手机的方向有关。实际上,许多人更喜欢地球固定的坐标系,但手机不知道这一点。 您可以使用外部线索(GPS,磁场,陀螺仪,重力,地平线等)来尝试对齐它们,但仅根据加速度计提供的单个任意读数,信息并不足够。
定义:
加速度矢量:这是加速度计的x、y、z读数(每个读数都取决于手机的方向),有时写成A=(ax,ay,az)。
加速度大小: 这是 a=sqrt(ax2 + ay2 + az2), 它不应该取决于手机的方向(如果不同的轴被校准为相同)。如果手机静止,这基本上只是重力的读数。请注意,使用此测量方法会丢失加速度向量中的许多信息。
归一化加速度: 加速度方向,其大小为1,即 A/a。
地球坐标系下的加速度: 我认为这是您真正想要的,但没有简单的方法来获取它,而且即使您能够获取它,一开始看起来可能并不像您想象的那么有用。
滑雪:
我认为您有很大的机会通过加速度计的测量结果确定某人是否在滑雪。类似颠簸和转弯等事情都可以通过加速度计得到明显区别。对于这些情况,我会使用完整的加速度向量。例如,在转弯时,加速度大小会保持大致恒定,而方向会扫过目标方向。还要注意,自由落体(即,基本上每当滑雪者没有脚/臀部等接触地面时,无论他们是从颠簸/起跳时向上运动,还是从缆车上掉落),加速度大小在自由落体时将为零。对于缆车,似乎它很可能在一个单一平面内具有明显的节奏性摇摆。
所有这些事情都是可以解决的。如果你真的想要解决这个问题,我建议你在滑雪时记录你加速计的数据,并尝试根据数据的特征确定何时在滑雪。(我的猜测是,你在这方面最大的难题可能是数学,因为可能比较棘手来设计一个可以区分滑雪签名的算法,所以建议复习向量数学、点积和叉积等知识。此外,我认为还应该了解一些傅里叶变换或FFT的知识,以便更好地区分滑雪与坐椅子缆车时的时间和频率特征。)
你也可以结合GPS测量,虽然不太可靠,但至少可以用来检验你的算法。
您可以使用以下方法计算加速度,无论手机的方向如何:
a = sqrt(x*x + y*y + z*z)
其中a
是绝对加速度,而x
、y
和z
则分别代表手机的三个轴向的加速度数值。
z
,但它们在获取方式上可能都很相似)。 - Alex Turpin考虑使用GPS。在我使用的飞行记录应用程序中,我使用加速度(尽管是绝对值,而不是向量)来过滤嘈杂的GPS数据(我删除加速度不合理的速度变化位置):
/**
* Remove noise from the measurement of the location.
* @param loc a location
* @return Answer <code>false</code> iff the location should not be used.
*/
private boolean filterNoise(final Location loc) {
if( ! loc.hasSpeed() )
return true;
if( this.recentSpeeds.isEmpty() ) { // rescentSpeeds is a queue of locations
this.recentSpeeds.add(loc);
return true;
}
final Location lastFix = this.recentSpeeds.getHead();
final long delta_t = (loc.getTime() - lastFix.getTime()) / 1000;
if( delta_t == 0 )
return false;
final float delta_v = loc.getSpeed() - lastFix.getSpeed();
final float a = delta_v / delta_t;
if( Math.abs(a) <= AccelThreshold ) {
this.recentSpeeds.add(loc);
return true;
}
return false;
}
如果您使用上一个修正点和当前修正点的坐标计算速度,则可以得到矢量加速度。