Intereting Posts
Скрытие заголовка панели действий не работает в старых версиях Android (с помощью ActionBarSherlock) Быстрое приложение для Android – Java или родное? Cordova phonegap с использованием внешней веб-страницы в приложении, сохраняя верхний / нижний колонтитул (для навигации) OnTouchListener on Activity никогда не вызывает Как добавить пользовательские свойства / значения в файл манифеста Android? Как я могу получать уведомления о том, что Snackbar уволился? Пересчитать ScrollView на разных представлениях ViewFlipper? Лучшая практика внедрения обратной связи Retrofit для воссозданной деятельности? Отключить звук на ExoPlayer Отображение раскрывающегося списка панели действий Android на элемент click Android-приложение Gridview OnScrollListener ScrollUp и ScrollDown Телефонный интернет-телефон не работает Создать режим выпуска приложений Android Android: отключен звук уведомления Android, Сделать изображение по URL-адресу, равному изображению ImageView

Компас в Android

Я пытаюсь запрограммировать компас с Android с помощью ускорителя и датчика магнитного поля, теперь мне интересно, как получить правильный угол для моего компаса.

Я читаю значения акселерометра и датчика магнитного поля в «accele» и «magne» соответственно. Чтобы получить угол, я выполняю следующее:

float R[] = new float[9]; float I[] = new float[9]; boolean success = SensorManager.getRotationMatrix(R, I, accele, magne); if(success) { float orientation[] = new float[3]; SensorManager.getOrientation(R, orientation); azimuth = orientation[0]; // contains azimuth, pitch, roll .... 

Позже, я использую матрицу вращения, чтобы поместить мою иглу:

 rotation.setRotate(azimuth, compass.getWidth() / 2, compass.getHeight() / 2); canvas.drawBitmap(needle, rotation, null); 

Теперь в документации на getOrientation говорится, что ориентация [0] должна быть вращением вокруг оси z. В документации для TYPE_ORIENTATION говорится, что «азимут, угол между магнитным северным направлением и осью y, вокруг оси z (от 0 до 359). 0 = север, 90 = восток, 180 = юг, 270 = запад».

Мой азимут, однако, не находится между 0 и 359, а примерно от -2 до 2. Что такое азимут от getOrientation и как его преобразовать под углом?

Solutions Collecting From Web of "Компас в Android"

Используйте для преобразования из заданного азимута в радианах (-PI, + PI) в градусы (0, 360)

 float azimuthInRadians = orientation[0]; float azimuthInDegress = (float)Math.toDegrees(azimuthInRadians); if (azimuthInDegress < 0.0f) { azimuthInDegress += 360.0f; } 

Имена переменных, используемые для удобства 😉

Фрагмент кода можно получить из https://github.com/iutinvg/compass

Он не использует устаревшие вещи, применяет фильтр нижних частот.

Я нашел это в ApiDemos Google:

  /* * Copyright (C) 2007 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.example.android.apis.graphics; import android.app.Activity; import android.content.Context; import android.graphics.*; import android.hardware.SensorListener; import android.hardware.SensorManager; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.os.SystemClock; import android.util.Config; import android.util.Log; import android.view.View; public class Compass extends GraphicsActivity { private static final String TAG = "Compass"; private SensorManager mSensorManager; private SampleView mView; private float[] mValues; private final SensorListener mListener = new SensorListener() { public void onSensorChanged(int sensor, float[] values) { if (Config.LOGD) Log.d(TAG, "sensorChanged (" + values[0] + ", " + values[1] + ", " + values[2] + ")"); mValues = values; if (mView != null) { mView.invalidate(); } } public void onAccuracyChanged(int sensor, int accuracy) { // TODO Auto-generated method stub } }; @Override protected void onCreate(Bundle icicle) { super.onCreate(icicle); mSensorManager = (SensorManager)getSystemService(Context.SENSOR_SERVICE); mView = new SampleView(this); setContentView(mView); } @Override protected void onResume() { if (Config.LOGD) Log.d(TAG, "onResume"); super.onResume(); mSensorManager.registerListener(mListener, SensorManager.SENSOR_ORIENTATION, SensorManager.SENSOR_DELAY_GAME); } @Override protected void onStop() { if (Config.LOGD) Log.d(TAG, "onStop"); mSensorManager.unregisterListener(mListener); super.onStop(); } private class SampleView extends View { private Paint mPaint = new Paint(); private Path mPath = new Path(); private boolean mAnimate; private long mNextTime; public SampleView(Context context) { super(context); // Construct a wedge-shaped path mPath.moveTo(0, -50); mPath.lineTo(-20, 60); mPath.lineTo(0, 50); mPath.lineTo(20, 60); mPath.close(); } @Override protected void onDraw(Canvas canvas) { Paint paint = mPaint; canvas.drawColor(Color.WHITE); paint.setAntiAlias(true); paint.setColor(Color.BLACK); paint.setStyle(Paint.Style.FILL); int w = canvas.getWidth(); int h = canvas.getHeight(); int cx = w / 2; int cy = h / 2; canvas.translate(cx, cy); if (mValues != null) { canvas.rotate(-mValues[0]); } canvas.drawPath(mPath, mPaint); } @Override protected void onAttachedToWindow() { mAnimate = true; super.onAttachedToWindow(); } @Override protected void onDetachedFromWindow() { mAnimate = false; super.onDetachedFromWindow(); } } } 

Как вы можете видеть, вы получаете степень от 0 до 360