车辆移动时,Android指南针无法正常工作

时间:2018-06-08 05:24:05

标签: android google-maps android-mapview android-sensors compass-geolocation

我试图弄清楚如何将设备标记指向用户前进的位置。我尝试了下面的代码来获得真北和用户前进之间的方位角。找到轴承后,我会将其应用到设备标记并根据轴承旋转它,但它仅在设备不移动时才有效。

我尝试了以下链接中找到的代码。

Code Source Link

// raw inputs from Android sensors
float m_Norm_Gravity;           // length of raw gravity vector received in onSensorChanged(...).  NB: should be about 10
float[] m_NormGravityVector = m_NormMagFieldValues = null;;    // Normalised gravity vector, (i.e. length of this vector is 1), which points straight up into space
float m_Norm_MagField;          // length of raw magnetic field vector received in onSensorChanged(...).
float[] m_NormMagFieldValues;   // Normalised magnetic field vector, (i.e. length of this vector is 1)

// accuracy specifications. SENSOR_UNAVAILABLE if unknown, otherwise SensorManager.SENSOR_STATUS_UNRELIABLE, SENSOR_STATUS_ACCURACY_LOW, SENSOR_STATUS_ACCURACY_MEDIUM or SENSOR_STATUS_ACCURACY_HIGH
int m_GravityAccuracy;          // accuracy of gravity sensor
int m_MagneticFieldAccuracy;    // accuracy of magnetic field sensor

// values calculated once gravity and magnetic field vectors are available
float[] m_NormEastVector = new float[3];       // normalised cross product of raw gravity vector with magnetic field values, points east
float[] m_NormNorthVector = new float[3];      // Normalised vector pointing to magnetic north
boolean m_OrientationOK = false;        // set true if m_azimuth_radians and m_pitch_radians have successfully been calculated following a call to onSensorChanged(...)
float m_azimuth_radians;        // angle of the device from magnetic north
float m_pitch_radians;          // tilt angle of the device from the horizontal.  m_pitch_radians = 0 if the device if flat, m_pitch_radians = Math.PI/2 means the device is upright.
float m_pitch_axis_radians;     // angle which defines the axis for the rotation m_pitch_radians



@Override
public void onSensorChanged(SensorEvent sensorEvent) {

    int SensorType = sensorEvent.sensor.getType();
    switch(SensorType) {
        case Sensor.TYPE_GRAVITY:
            if (m_NormGravityVector == null) m_NormGravityVector = new float[3];
            System.arraycopy(sensorEvent.values, 0, m_NormGravityVector, 0, m_NormGravityVector.length);
            m_Norm_Gravity = (float)Math.sqrt(m_NormGravityVector[0]*m_NormGravityVector[0] + m_NormGravityVector[1]*m_NormGravityVector[1] + m_NormGravityVector[2]*m_NormGravityVector[2]);
            for(int i=0; i < m_NormGravityVector.length; i++) m_NormGravityVector[i] /= m_Norm_Gravity;
            break;
        case Sensor.TYPE_MAGNETIC_FIELD:
            if (m_NormMagFieldValues == null) m_NormMagFieldValues = new float[3];
            System.arraycopy(sensorEvent.values, 0, m_NormMagFieldValues, 0, m_NormMagFieldValues.length);
            m_Norm_MagField = (float)Math.sqrt(m_NormMagFieldValues[0]*m_NormMagFieldValues[0] + m_NormMagFieldValues[1]*m_NormMagFieldValues[1] + m_NormMagFieldValues[2]*m_NormMagFieldValues[2]);
            for(int i=0; i < m_NormMagFieldValues.length; i++) m_NormMagFieldValues[i] /= m_Norm_MagField;
            break;
    }
    if (m_NormGravityVector != null && m_NormMagFieldValues != null) {
        // first calculate the horizontal vector that points due east
        float East_x = m_NormMagFieldValues[1] * m_NormGravityVector[2] - m_NormMagFieldValues[2] * m_NormGravityVector[1];
        float East_y = m_NormMagFieldValues[2] * m_NormGravityVector[0] - m_NormMagFieldValues[0] * m_NormGravityVector[2];
        float East_z = m_NormMagFieldValues[0] * m_NormGravityVector[1] - m_NormMagFieldValues[1] * m_NormGravityVector[0];
        float norm_East = (float) Math.sqrt(East_x * East_x + East_y * East_y + East_z * East_z);
        if (m_Norm_Gravity * m_Norm_MagField * norm_East < 0.1f) {  // Typical values are  > 100.
            m_OrientationOK = false; // device is close to free fall (or in space?), or close to magnetic north pole.
        } else {
            m_NormEastVector[0] = East_x / norm_East;
            m_NormEastVector[1] = East_y / norm_East;
            m_NormEastVector[2] = East_z / norm_East;

            // next calculate the horizontal vector that points due north
            float M_dot_G = (m_NormGravityVector[0] * m_NormMagFieldValues[0] + m_NormGravityVector[1] * m_NormMagFieldValues[1] + m_NormGravityVector[2] * m_NormMagFieldValues[2]);
            float North_x = m_NormMagFieldValues[0] - m_NormGravityVector[0] * M_dot_G;
            float North_y = m_NormMagFieldValues[1] - m_NormGravityVector[1] * M_dot_G;
            float North_z = m_NormMagFieldValues[2] - m_NormGravityVector[2] * M_dot_G;
            float norm_North = (float) Math.sqrt(North_x * North_x + North_y * North_y + North_z * North_z);
            m_NormNorthVector[0] = North_x / norm_North;
            m_NormNorthVector[1] = North_y / norm_North;
            m_NormNorthVector[2] = North_z / norm_North;

            // take account of screen rotation away from its natural rotation
            int rotation = getActivity().getWindowManager().getDefaultDisplay().getRotation();
            float screen_adjustment = 0;
            switch (rotation) {
                case Surface.ROTATION_0:
                    screen_adjustment = 0;
                    break;
                case Surface.ROTATION_90:
                    screen_adjustment = (float) Math.PI / 2;
                    break;
                case Surface.ROTATION_180:
                    screen_adjustment = (float) Math.PI;
                    break;
                case Surface.ROTATION_270:
                    screen_adjustment = 3 * (float) Math.PI / 2;
                    break;
            }
            // NB: the rotation matrix has now effectively been calculated. It consists of the three vectors m_NormEastVector[], m_NormNorthVector[] and m_NormGravityVector[]

            // calculate all the required angles from the rotation matrix
            // NB: see https://math.stackexchange.com/questions/381649/whats-the-best-3d-angular-co-ordinate-system-for-working-with-smartfone-apps
            float sin = m_NormEastVector[1] - m_NormNorthVector[0], cos = m_NormEastVector[0] + m_NormNorthVector[1];
            m_azimuth_radians = (float) (sin != 0 && cos != 0 ? Math.atan2(sin, cos) : 0);
            m_pitch_radians = (float) Math.acos(m_NormGravityVector[2]);
            sin = -m_NormEastVector[1] - m_NormNorthVector[0];
            cos = m_NormEastVector[0] - m_NormNorthVector[1];
            float aximuth_plus_two_pitch_axis_radians = (float) (sin != 0 && cos != 0 ? Math.atan2(sin, cos) : 0);
            m_pitch_axis_radians = (float) (aximuth_plus_two_pitch_axis_radians - m_azimuth_radians) / 2;
            m_azimuth_radians += screen_adjustment;
            m_pitch_axis_radians += screen_adjustment;
            m_OrientationOK = true;

            currentAzimuth = (float) Math.toDegrees(m_azimuth_radians);
        }
    }



}






@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
    int SensorType = sensor.getType();
    switch(SensorType) {
        case Sensor.TYPE_GRAVITY: m_GravityAccuracy = accuracy; break;
        case Sensor.TYPE_MAGNETIC_FIELD: m_MagneticFieldAccuracy = accuracy; break;
    }
}

0 个答案:

没有答案