当前位置: 首页 > 知识库问答 >
问题:

在android中正确计算真标题

师博
2023-03-14

我的需求是在指南针模式下的Google maps Apps(点击两次Current location button时可以看到演示):

  • 在此指南针模式下,地图总是旋转一个角度,以便蓝点箭头始终指向顶部屏幕。

但我不知道如何计算正确的方位方位角,俯仰,滚动值。

public void onSensorChanged(SensorEvent sensorEvent) {
        switch (sensorEvent.sensor.getType()) {
            case Sensor.TYPE_ACCELEROMETER:
                System.arraycopy(sensorEvent.values, 0, mAccelerometers, 0, 3);
                break;
            case Sensor.TYPE_MAGNETIC_FIELD:
                System.arraycopy(sensorEvent.values, 0, mMagnetometers, 0, 3);
                break;
            default:
                break;
        }
        float[] rotationMatrix = new float[9];
        boolean success =
                    SensorManager.getRotationMatrix(rotationMatrix, null, mAccelerometers, mMagnetometers);
         if (success) {
             SensorManager.getOrientation(rotationMatrix, mOrientation);
             float azimuth = Math.toDegrees(mOrientation[0]);
             float pitch = Math.toDegrees(mOrientation[1]);
             float roll = Math.toDegrees(mOrientation[2]);
         }
         // cal to updateBearing();
    }

在iOS中,clheading可以返回真正的heading。在android中是否有一个类具有相同的特性,或者如何计算它?

共有2个答案

丰飞龙
2023-03-14

方位角和位置是计算航向所需的唯一参数。

角度计算和转换的惯例是按以下顺序使用:
1)方位角
2)俯仰
3)滚转

诸俊才
2023-03-14

检查下面的链接,查看您的问题轴承-示例

轴承-示例

下面的答案也与你的问题相似。

我如何得到正确的方位?

package ymc.ch.bearingexample;
import android.content.Context;
import android.hardware.GeomagneticField;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.util.Log;

/**
 * Utility class that provides bearing values to true north.
 */
public class BearingToNorthProvider implements SensorEventListener, LocationListener
{
    public static final String TAG = "BearingToNorthProvider";

    /**
     * Interface definition for a callback to be invoked when the bearing changes.
     */
    public static interface ChangeEventListener {
        /**
         * Callback method to be invoked when the bearing changes.
         * @param bearing the new bearing value
         */
        void onBearingChanged(double bearing);
    }

    private final SensorManager mSensorManager;
    private final LocationManager mLocationManager;
    private final Sensor mSensorAccelerometer;
    private final Sensor mSensorMagneticField;

    // some arrays holding intermediate values read from the sensors, used to calculate our azimuth
    // value

    private float[] mValuesAccelerometer;
    private float[] mValuesMagneticField;
    private float[] mMatrixR;
    private float[] mMatrixI;
    private float[] mMatrixValues;

    /**
     * minimum change of bearing (degrees) to notify the change listener
     */
    private final double mMinDiffForEvent;

    /**
     * minimum delay (millis) between notifications for the change listener
     */
    private final double mThrottleTime;

    /**
     * the change event listener
     */
    private ChangeEventListener mChangeEventListener;

    /**
     * angle to magnetic north
     */
    private AverageAngle mAzimuthRadians;

    /**
     * smoothed angle to magnetic north
     */
    private double mAzimuth = Double.NaN;

    /**
     * angle to true north
     */
    private double mBearing = Double.NaN;

    /**
     * last notified angle to true north
     */
    private double mLastBearing = Double.NaN;

    /**
     * Current GPS/WiFi location
     */
    private Location mLocation;

    /**
     * when we last dispatched the change event
     */
    private long mLastChangeDispatchedAt = -1;

    /**
     * Default constructor.
     *
     * @param context Application Context
     */
    public BearingToNorthProvider(Context context) {
        this(context, 10, 0.5, 50);
    }

    /**
     * @param context Application Context
     * @param smoothing the number of measurements used to calculate a mean for the azimuth. Set
     *                      this to 1 for the smallest delay. Setting it to 5-10 to prevents the
     *                      needle from going crazy
     * @param minDiffForEvent minimum change of bearing (degrees) to notify the change listener
     * @param throttleTime minimum delay (millis) between notifications for the change listener
     */
    public BearingToNorthProvider(Context context, int smoothing, double minDiffForEvent, int throttleTime)
    {
        mSensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
        mSensorAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
        mLocationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
        mSensorMagneticField = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);

        mValuesAccelerometer = new float[3];
        mValuesMagneticField = new float[3];

        mMatrixR = new float[9];
        mMatrixI = new float[9];
        mMatrixValues = new float[3];

        mMinDiffForEvent = minDiffForEvent;
        mThrottleTime = throttleTime;

        mAzimuthRadians = new AverageAngle(smoothing);
    }

    //==============================================================================================
    // Public API
    //==============================================================================================

    /**
     * Call this method to start bearing updates.
     */
    public void start()
    {
        mSensorManager.registerListener(this, mSensorAccelerometer, SensorManager.SENSOR_DELAY_UI);
        mSensorManager.registerListener(this, mSensorMagneticField, SensorManager.SENSOR_DELAY_UI);

        for (final String provider : mLocationManager.getProviders(true)) {
            if (LocationManager.GPS_PROVIDER.equals(provider)
                    || LocationManager.PASSIVE_PROVIDER.equals(provider)
                    || LocationManager.NETWORK_PROVIDER.equals(provider)) {
                if (mLocation == null) {
                    mLocation = mLocationManager.getLastKnownLocation(provider);
                }
                mLocationManager.requestLocationUpdates(provider, 0, 100.0f, this);
            }
        }
    }

    /**
     * call this method to stop bearing updates.
     */
    public void stop()
    {
        mSensorManager.unregisterListener(this, mSensorAccelerometer);
        mSensorManager.unregisterListener(this, mSensorMagneticField);
        mLocationManager.removeUpdates(this);
    }

    /**
     * @return current bearing
     */
    public double getBearing()
    {
        return mBearing;
    }

    /**
     * Returns the bearing event listener to which bearing events must be sent.
     * @return the bearing event listener
     */
    public ChangeEventListener getChangeEventListener()
    {
        return mChangeEventListener;
    }

    /**
     * Specifies the bearing event listener to which bearing events must be sent.
     * @param changeEventListener the bearing event listener
     */
    public void setChangeEventListener(ChangeEventListener changeEventListener)
    {
        this.mChangeEventListener = changeEventListener;
    }

    //==============================================================================================
    // SensorEventListener implementation
    //==============================================================================================

    @Override
    public void onSensorChanged(SensorEvent event)
    {
        switch (event.sensor.getType()) {
            case Sensor.TYPE_ACCELEROMETER:
                System.arraycopy(event.values, 0, mValuesAccelerometer, 0, 3);
                break;
            case Sensor.TYPE_MAGNETIC_FIELD:
                System.arraycopy(event.values, 0, mValuesMagneticField, 0, 3);
                break;
        }

        boolean success = SensorManager.getRotationMatrix(mMatrixR, mMatrixI,
                mValuesAccelerometer,
                mValuesMagneticField);

        // calculate a new smoothed azimuth value and store to mAzimuth
        if (success) {
            SensorManager.getOrientation(mMatrixR, mMatrixValues);
            mAzimuthRadians.putValue(mMatrixValues[0]);
            mAzimuth = Math.toDegrees(mAzimuthRadians.getAverage());
        }

        // update mBearing
        updateBearing();
    }

    @Override
    public void onAccuracyChanged(Sensor sensor, int i) {   }

    //==============================================================================================
    // LocationListener implementation
    //==============================================================================================

    @Override
    public void onLocationChanged(Location location)
    {
        // set the new location
        this.mLocation = location;

        // update mBearing
        updateBearing();
    }

    @Override
    public void onStatusChanged(String s, int i, Bundle bundle) {   }

    @Override
    public void onProviderEnabled(String s) {   }

    @Override
    public void onProviderDisabled(String s) {   }

    //==============================================================================================
    // Private Utilities
    //==============================================================================================

    private void updateBearing()
    {
        if (!Double.isNaN(this.mAzimuth)) {
            if(this.mLocation == null) {
                Log.w(TAG, "Location is NULL bearing is not true north!");
                mBearing = mAzimuth;
            } else {
                mBearing = getBearingForLocation(this.mLocation);
            }

            // Throttle dispatching based on mThrottleTime and minDiffForEvent
            if( System.currentTimeMillis() - mLastChangeDispatchedAt > mThrottleTime &&
                (Double.isNaN(mLastBearing) || Math.abs(mLastBearing - mBearing) >= mMinDiffForEvent)) {
                mLastBearing = mBearing;
                if(mChangeEventListener != null) {
                    mChangeEventListener.onBearingChanged(mBearing);
                }
                mLastChangeDispatchedAt = System.currentTimeMillis();
            }
        }
    }

    private double getBearingForLocation(Location location)
    {
        return mAzimuth + getGeomagneticField(location).getDeclination();
    }

    private GeomagneticField getGeomagneticField(Location location)
    {
        GeomagneticField geomagneticField = new GeomagneticField(
                (float)location.getLatitude(),
                (float)location.getLongitude(),
                (float)location.getAltitude(),
                System.currentTimeMillis());
        return geomagneticField;
    }
}
 类似资料:
  • 我正在尝试匹配从服务器下载的文件的md5sum。只有当总和匹配时,处理才会继续。 上面的代码并没有每次为某些文件正确提供md5sum。 当我去控制台检查md5sum时 下载文件的vimdiff未提供任何差异。。下载后的文件是正确的。 我无法在上述代码中看到问题。 我正在尝试更改缓冲区大小。但没有运气,所以我猜这不是因为缓冲区大小等。 问候Dheeraj Joshi

  • 我在一个项目中工作,其中在线考试是一个部分,我做这为我的SEM。考试。我正在创建一个在线考试系统(项目的一部分),在那里我可以从数据库中提取问题和答案,但我不能计算正确的答案。我需要帮助。任何帮助都将非常感谢,因为我需要尽快做这件事。 编码是使用jsp scriplet代码来获取数据的: 现在代码看看正确的答案。这里我卡住了... 我可以看到在jsp页面中选择的数据,也可以看到正确的ans,但在计

  • 问题内容: 我遇到了一个问题,我正在开发一个应该能够进行一些数学计算的应用程序。这些计算必须是准确的(或者显然不是错误的) 但是这个简单的代码 给我一个错误的结果c不是预期的0.003048而是0.0030480000000000004这显然是错误的。 第二个代码片段给出了正确的结果。 我知道在使用计算机进行计算时,并不是所有的浮点运算都是精确的,但是我不知道如何解决这个问题。 提前致谢! 路德维

  • 我需要阅读由AutoCAD导出为PDF的平面图,并使用PDFBox在上面放置一些带有文本的标记。除了文字宽度的计算之外,一切都很顺利,文字的宽度写在标记旁边。 我浏览了整个PDF规范,详细阅读了其中涉及图形和文本的部分,但没有任何效果。据我所知,字形坐标空间设置在用户坐标空间的1/1000处。因此,宽度需要放大1000倍,但仍然是实际宽度的一小部分。 这就是我为定位文本所做的: *0.043f可以

  • 晚上好!我是一名律师,我经常要计算被判刑的人多久才能获得福利,比如假释。 它的工作原理如下: 首先,我需要得到一些主要变量,比如那个人开始服刑的那一天(他被捕的那一天)。这将是第一项福利的基准日期。假设有人在2014年11月12日被捕。 我必须做的第二件事是知道每项罪行的判决是什么(有时这个人被判犯有不止一项罪行,对于每项罪行,都有不同的计算方法。假设这个人被判犯有两项罪行: 对于第一项罪行(这是