但是问题在于转换加速度计数据以计算位移。
我知道需要整合两次加速度。数据以获取位置。
使用四元数,我可以旋转加速度矢量,然后将其轴求和以获取速度,然后再次进行相同操作以获取位置。但这不是那样的。首先,将传感器移到某个位置,然后再移回去,不会像以前那样给我相同的位置。问题是,尽管传感器传来的加速度数据为零,但当我将传感器放回原处并保持静止不动时,速度不会变为零。
这里是一个示例(最初是类似this):
重力:-0.10 -0.00 1.00
原始加速度:-785 -28 8135
缩放至+ -g后加速:-0.10 -0.00 0.99
结果使用四元数旋转加速度矢量后:0.00 -0.00 -0.00
移动传感器并将其放回后,其加速度变为:
0.00 -0.00 -0.01
0.00 -0.00- 0.01
0.00 -0.00 -0.00
0.00 -0.00 -0.01
依此类推。
如果我对其进行积分,则Z的位置会逐渐增大。
但最严重的问题是速度不会恢复为零
例如,如果我一次移动传感器并将其放回原处,速度将为:
-0.089对于vx,对于
0.15对于vy
经过几次这样的移动后,它变为:
1.22对于vx
1.08对于vy
-8.63对于vz
,接着又是这样的运动:
vx -1.43
vy 1.23
vz -9.7
如果传感器不移动但Z缓慢变化,则x和y不变。
尽管四元数根本没有改变。
执行该任务的正确方法应该是什么?
这是集成代码的一部分:
vX += wX * speed;
vY += wY * speed;
vZ += wZ * speed;
posX += vX * speed;
posY += vY * speed;
posZ += vZ * speed;
当前将速度设置为1只是为了测试其工作原理。
编辑1:这是用于检索四元数和加速数据,旋转并补偿重力的代码并获取最终的加速度数据。
// display initial world-frame acceleration, adjusted to remove gravity
// and rotated based on known orientation from quaternion
mpu.dmpGetQuaternion(&q, fifoBuffer);
mpu.dmpGetAccel(&aaReal, fifoBuffer);
mpu.dmpGetGravity(&gravity, &q);
//Serial.print("gravity\t");
Serial.print(gravity.x);
Serial.print("\t");
Serial.print(gravity.y);
Serial.print("\t");
Serial.print(gravity.z);
Serial.print("\t");
//Serial.print("accell\t");
Serial.print(aaReal.x);
Serial.print("\t");
Serial.print(aaReal.y);
Serial.print("\t");
Serial.print(aaReal.z);
Serial.print("\t");
float val = 4.0f;
float ax = val * (float)aaReal.x / 32768.0f;
float ay = val * (float)aaReal.y / 32768.0f;
float az = val * (float)aaReal.z / 32768.0f;
theWorldF.x = ax;
theWorldF.y = ay;
theWorldF.z = az;
//Serial.print("scaled_accel\t");
Serial.print(ax);
Serial.print("\t");
Serial.print(ay);
Serial.print("\t");
Serial.print(az);
Serial.print("\t");
theWorldF.x -= gravity.x;
theWorldF.y -= gravity.y;
theWorldF.z -= gravity.z;
theWorldF.rotate(&q);
//gravity.rotate(&q);
//Serial.print("gravity_compensated_accel\t");
Serial.print(theWorldF.x);
Serial.print("\t");
Serial.print(theWorldF.y);
Serial.print("\t");
Serial.print(theWorldF.z);
Serial.print("\t");
Serial.print(deltaTime);
Serial.println();
编辑2:
dmpGetQuaternion,dmpGetAccel函数只是从中读取MPU的FIFO缓冲区。
dmpGetGravity是:
uint8_t MPU6050::dmpGetGravity(VectorFloat *v, Quaternion *q) {
v -> x = 2 * (q -> x*q -> z - q -> w*q -> y);
v -> y = 2 * (q -> w*q -> x + q -> y*q -> z);
v -> z = q -> w*q -> w - q -> x*q -> x - q -> y*q -> y + q -> z*q -> z;
return 0;
}
编辑3:
使用MPU 9150的库:
https:// github.com/sparkfun/MPU-9150_Breakout
编辑4:另一个示例
重力矢量:-1.00 -0.02 0.02
原始加速度数据:-8459 -141 125
加速度数据刻度(+ -2g范围):-1.03 -0.02 0.02
重力补偿和加速度数据旋转:-0.01 0.00 0.33
#1 楼
您正在尝试采用以下形式进行数值积分:$$
\ mbox {积分值} + = \ mbox {微分} * \ mbox {经过的时间}
$$
代替
elapsed time
的是一些叫做speed
的值。尝试在中断上设置数字积分代码,其中中断时序将替代elapsed time
。 我不确定您要使用哪种方法从四元数转换为旋转的加速度矢量,但是我想指出的是,您不能像这样对四元数进行数值积分具有加速度或速度。有关更多详细信息,请参见本文档的第11页,但简要地讲,请使用陀螺仪角加速度$ \ omega_x \ omega_y \ omega_z $和现有的四元数$ q(t)$并计算四元数导数:
$$
\ dot {q}(t)= \ frac {1} {2} \ left [\ begin {array} {cccc}
0&\ omega_z&-\ omega_y&\ omega_x \ \
-\ omega_z&0&\ omega_x&\ omega_y \\
\ omega_y&-\ omega_x&0&\ omega_z \\
-\ omega_x&-\ omega_y&-\ omega_z &0 \ end {array} \ right] q(t)
$$
然后对它们进行数值积分,这样,对于离散系统,
$$
q_k = q_ {k-1} + \ dot {q} _k * dT
$$
您没有提供任何有关更新方式的代码加速向量,没有关于如何获得四元数的代码,等等,因此不可能给您比这更具体的反馈。
评论
$ \ begingroup $
我只想指出,您的四元数更新不会导致单位四元数(不再是单位范数)。取而代之的是,可以通过(四元数)乘法更新四元数,从而保持单位约束。
$ \ endgroup $
– kamek
15年12月14日在17:34
$ \ begingroup $
@kamek-是的,您的陈述进一步证明了以下事实:四元数的数字积分不是微不足道的过程,并且不采用“常规”项的数字积分形式。
$ \ endgroup $
–卡盘
15年12月14日在18:40
$ \ begingroup $
@Chuck实际上,我只是使用MPU 9150的内部运动处理器,如果启用,它会进行四元数估计和滤波。为了加速,我只是从传感器获取那些数据。每次中断,我都会获得新的四元数和加速数据。我不能只使用该四元数,也应该整合四元数吗?现在有点困惑。
$ \ endgroup $
–最大
15年12月14日在19:48
$ \ begingroup $
@Chuck对我也一样。这是进行四元数计算的dmp文档:digikey.com/document-redirector?doc=https://www.digikey.com/…
$ \ endgroup $
–最大
2015年12月15日上午8:13
$ \ begingroup $
我只是通过提供的四元数来旋转加速度矢量。
$ \ endgroup $
–最大
2015年12月15日上午8:13