如何在 CMRotationMatrix 上应用过滤器?也许卡尔曼过滤器。我需要修复CMRotationMatrix(transformFromCMRotationMatrix)的噪声,得到结果矩阵的线性值
这个矩阵值将转换为XYZ,在我的情况下,我在2D屏幕上模拟3D:
//将矩阵转换为x,y
vec4f_t v;
multiplyMatrixAndVector(v, projectionCameraTransform, boxMatrix);
float x = (v[0] / v[3] + 1.0f) * 0.5f;
float y = (v[1] / v[3] + 1.0f) * 0.5f;
CGPointMake(x * self.bounds.size.width, self.bounds.size.height - (y * self.bounds.size.height));
码:
//定义变量
mat4f_t cameraTransform;
//启动显示链接循环
- (void)startDisplayLink
{
displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(onDisplayLink:)];
[displayLink setFrameInterval:1];
[displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
}
//停止显示链接循环
- (void)stopDisplayLink
{
[displayLink invalidate];
displayLink = nil;
}
//显示链接的事件
- (void)onDisplayLink:(id)sender
{
CMDeviceMotion *d = motionManager.deviceMotion;
if (d != nil) {
CMRotationMatrix r = d.attitude.rotationMatrix;
transformFromCMRotationMatrix(cameraTransform, &r);
[self setNeedsDisplay];
}
}
// [self setNeedDisplay]之前的函数触发器;
void transformFromCMRotationMatrix(vec4f_t mout, const CMRotationMatrix *m)
{
mout[0] = (float)m->m11;
mout[1] = (float)m->m21;
mout[2] = (float)m->m31;
mout[3] = 0.0f;
mout[4] = (float)m->m12;
mout[5] = (float)m->m22;
mout[6] = (float)m->m32;
mout[7] = 0.0f;
mout[8] = (float)m->m13;
mout[9] = (float)m->m23;
mout[10] = (float)m->m33;
mout[11] = 0.0f;
mout[12] = 0.0f;
mout[13] = 0.0f;
mout[14] = 0.0f;
mout[15] = 1.0f;
}
// Matrix-vector和matrix-matricx乘法例程
void multiplyMatrixAndVector(vec4f_t vout, const mat4f_t m, const vec4f_t v)
{
vout[0] = m[0]*v[0] + m[4]*v[1] + m[8]*v[2] + m[12]*v[3];
vout[1] = m[1]*v[0] + m[5]*v[1] + m[9]*v[2] + m[13]*v[3];
vout[2] = m[2]*v[0] + m[6]*v[1] + m[10]*v[2] + m[14]*v[3];
vout[3] = m[3]*v[0] + m[7]*v[1] + m[11]*v[2] + m[15]*v[3];
}
答案 0 :(得分:1)
一般来说,我会区分提高信噪比和消除信号。
信号改善
如果您真的想要比Apple已经实施传感器融合算法的Core Motion更好,请为具有不确定结果的长期项目做好准备。在这种情况下,您最好采用原始加速度计和陀螺仪信号来构建您自己的传感器融合算法,但您必须关注许多问题,如漂移,不同iPhone版本的硬件依赖性,传感器内的硬件差异一代,...所以我的建议:尽量避免它。
平滑
这仅仅意味着插入两个或更多信号并构建平均值。我不知道任何合适的方法直接用于旋转矩阵(可能有一个),但你可以使用quaternions代替(更多资源:OpenGL Tutorial Using Quaternions to represent rotation或Quaternion FAQ)。
这种插值的结果四元数可以与矢量相乘,以类似于矩阵方式获得投影(您可以查看Finding normal vector to iOS device以获取更多信息)。
表示旋转的两个单位四元数之间的插值可以使用Slerp来完成。在实践中,您将使用维基百科中描述为Geometric Slerp的内容。如果您有两个时间点 t1 和 t2 以及相应的四元数 q1 和 q2 且角距<他们之间的em> omega ,公式为:
q'(q1,q2,t)= sin((1-t)* omega)/ sin(ω)* q0 + sin(t * omega)/ sin(ω)* q1
t应为0.5,因为您需要两次旋转之间的平均值。 Omega可以通过点积计算:
cos(omega)= q1.q2 = w1 * w2 + x1 * x2 + y1 * y2 + z1 * z2
如果使用两个四元数的方法仍然不符合您的需要,可以使用slerp(slerp(q1,q2),slerp(q3,q4))重复此操作。一些说明:
github上的C ++项目pbrt包含一个四元数类,可以从中获得灵感。