电子罗盘-航向角计算

这里写图片描述

坐标变换

  • 手机初始状态accelerometer 与 magnetometer 读数为
    (假定初始状态为水平放置,如上图所示)
    (1) G 1 = [ a x 1 a y 1 a z 1 ] = [ 0 0 g ]

    (2) M 1 = [ m x 1 m y 1 m z 1 ] = [ c o s ( δ ) 0 s i n ( δ ) ]
  • 依上图坐标系,手机绕 x , y , z 轴旋转的变换矩阵为
    (3) C x ( θ ) = [ 1 0 0 0 c o s ( θ ) s i n ( θ ) 0 s i n ( θ ) c o s ( θ ) ]

    (4) C y ( ϕ ) = [ c o s ( ϕ ) 0 s i n ( ϕ ) 0 1 0 s i n ( ϕ ) 0 c o s ( ϕ ) ]

    (5) C z ( ψ ) = [ c o s ( ψ ) s i n ( ψ ) 0 s i n ( ψ ) c o s ( ψ ) 0 0 0 1 ]

姿态角计算

  • 下列计算均假设acclerometer读数基本稳定,即手机近似静止,可对加速度数据做低通滤波处理.
  • 旋转过后accelerometer与magnetometer读数为(基于机体坐标系,旋转次序 yaw->pitch ->roll)
    (6) G 2 = [ a x 2 a y 2 a z 2 ] = C y ( ϕ ) C x ( θ ) C z ( ψ ) G 1 = C y ( ϕ ) C x ( θ ) C z ( ψ ) [ 0 0 g ]

    (7) M 2 = [ m x 2 m y 2 m z 2 ] = C y ( ϕ ) C x ( θ ) C z ( ψ ) M 1 = C y ( ϕ ) C x ( θ ) C z ( ψ ) [ c o s ( δ ) 0 s i n ( δ ) ]
  • 计算翻滚角 ϕ
    由公式(6)可得,

    (8) (365) G 2 = [ a x 2 a y 2 a z 2 ] = C y ( ϕ ) C x ( θ ) C y ( ψ ) G 1 = C y ( ϕ ) C x ( θ ) C y ( ψ ) [ 0 0 g ] (366) = [ c o s ( ϕ ) 0 s i n ( ϕ ) 0 1 0 s i n ( ϕ ) 0 c o s ( ϕ ) ] [ 1 0 0 0 c o s ( θ ) s i n ( θ ) 0 s i n ( θ ) c o s ( θ ) ] [ c o s ( ψ ) s i n ( ψ ) 0 s i n ( ψ ) c o s ( ψ ) 0 0 0 1 ] [ 0 0 g ] (367) = [ c o s ( ϕ ) c o s ( ψ ) + s i n ( ϕ ) s i n ( θ ) s i n ( ψ ) s i n ( ϕ ) s i n ( θ ) c o s ( ψ ) c o s ( ϕ ) s i n ( ψ ) s i n ( ϕ ) c o s ( θ ) c o s ( θ ) s i n ( ψ ) c o s ( θ ) c o s ( ψ ) s i n ( θ ) c o s ( ϕ ) s i n ( θ ) s i n ( ψ ) s i n ( ϕ ) c o s ( ψ ) s i n ( ϕ ) s i n ( ψ ) + c o s ( ϕ ) s i n ( θ ) c o s ( ψ ) c o s ( ϕ ) c o s ( θ ) ] [ 0 0 g ] (368) = [ g s i n ( ϕ ) c o s ( θ ) g s i n ( θ ) g c o s ( ϕ ) c o s ( θ ) ]


    由公式(8)可得,
    a x 2 a z 2 = t a n ( ϕ )


    (9) ϕ = t a n ( a x 2 a z 2 )

  • 计算俯仰角 θ

    • 方法一:由公式(8)可得,
      a y 2 = g s i n ( θ )


      θ = a r c s i n ( a y 2 g )
      ,此时 g = s q r t ( a x 2 2 + a y 2 2 + a z 2 2 ) .
    • 方法二:已求得 ϕ 条件下,同由公式(8)得,
      a y 2 a x 2 s i n ( ϕ ) + a z 2 c o s ( ϕ ) = t a n ( θ )


      (10) θ = a r c t a n ( a y 2 a x 2 s i n ( ϕ ) + a z 2 c o s ( ϕ ) )
    • 方法一与方法二求得结果一致,本文采用方法一(android getOrientation()方法用的方法二)
  • 计算航向角 ψ
    由公式(7)可得,
    (11) (369) M 2 = [ m x 2 m y 2 m z 2 ] = C y ( ϕ ) C x ( θ ) C z ( ψ ) M 1 = C y ( ϕ ) C x ( θ ) C z ( ψ ) [ c o s ( δ ) 0 s i n ( δ ) ] (370) = [ c o s ( ϕ ) c o s ( ψ ) + s i n ( ϕ ) s i n ( θ ) s i n ( ψ ) s i n ( ϕ ) s i n ( θ ) c o s ( ψ ) c o s ( ϕ ) s i n ( ψ ) s i n ( ϕ ) c o s ( θ ) c o s ( θ ) s i n ( ψ ) c o s ( θ ) c o s ( ψ ) s i n ( θ ) c o s ( ϕ ) s i n ( θ ) s i n ( ψ ) s i n ( ϕ ) c o s ( ψ ) s i n ( ϕ ) s i n ( ψ ) + c o s ( ϕ ) s i n ( θ ) c o s ( ψ ) c o s ( ϕ ) c o s ( θ ) ] [ c o s ( δ ) 0 s i n ( δ ) ] (371) = [ c o s ( ϕ ) c o s ( ψ ) c o s ( δ ) + s i n ( ϕ ) s i n ( θ ) s i n ( ψ ) c o s ( δ ) + s i n ( ϕ ) c o s ( θ ) s i n ( δ ) c o s ( θ ) s i n ( ψ ) c o s ( δ ) s i n ( θ ) s i n ( δ ) c o s ( ϕ ) s i n ( θ ) s i n ( ψ ) c o s ( δ ) s i n ( ϕ ) c o s ( ψ ) c o s ( δ ) + c o s ( ϕ ) c o s ( θ ) s i n ( δ ) ]

    已知 θ ϕ 条件下,由上式可得:
    m x 2 s i n ( ϕ ) + m z 2 c o s ( ϕ ) = s i n ( θ ) s i n ( ψ ) c o s ( δ ) + c o s ( θ ) s i n ( δ )

    [ m x 2 s i n ( ϕ ) + m z 2 c o s ( ϕ ) ] s i n ( θ ) + m y 2 c o s ( θ ) =   s i n ( ψ ) c o s ( δ )

    m x 2 c o s ( ϕ ) m z 2 s i n ( ϕ ) = c o s ( ψ ) c o s ( δ )

    则:
    ψ = a r c t a n ( m x 2 s i n ( ϕ ) s i n ( θ ) + m z 2 c o s ( ϕ ) s i n ( θ ) + m y 2 c o s ( θ ) m x 2 c o s ( ϕ ) m z 2 s i n ( ϕ ) )

Android 应用

  • 依上述公式求取航向角为与x轴夹角,通过android api getOrientation()方法获取方位角为与y轴夹角.需做角度转换
  float yaw = (float) Math.toDegrees(ECompass.getYaw(accVals,magVals));
                //getOrientation获取方位角为与y轴夹角,本文计算方法求取方位角为与x轴夹角,角度需转换
                yaw -= 90;
                if(yaw<-180)
                    yaw += 360;
public class ECompass {

    private static float yaw;
    private static float pitch;
    private static float roll;
    //accVal,magVal为android phone 获取传感器原始数据
    public static float getYaw(float[] accVals, float[] magVals) {
        roll = (float)Math.atan2(accVals[0],accVals[2]);
        pitch = -(float)Math.atan(accVals[1]/(accVals[0]*Math.sin(roll)+accVals[2]*Math.cos(roll)));
        yaw = (float)Math.atan2(magVals[0]*Math.sin(roll)*Math.sin(pitch)+magVals[2]*Math.cos(roll)*Math.sin(pitch)+magVals[1]*Math.cos(pitch),
               magVals[0]*Math.cos(roll)-magVals[2]*Math.sin(roll));
        return yaw;
    }
}

猜你喜欢

转载自blog.csdn.net/shawn_shao/article/details/80695917
今日推荐