ArViewer  Android Version
Arvos - Augmented reality viewer open source
 All Classes Namespaces Files Functions Variables
ArvosRadarView.java
Go to the documentation of this file.
1 /*
2  Copyright (C) 2013, Peter Graf
3 
4  This file is part of Arvos - AR Viewer Open Source for Android.
5  Arvos is free software.
6 
7  This program is free software: you can redistribute it and/or modify
8  it under the terms of the GNU General Public License as published by
9  the Free Software Foundation, either version 3 of the License, or
10  (at your option) any later version.
11 
12  This program is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with this program. If not, see <http://www.gnu.org/licenses/>.
19 
20  For more information on the AR Viewer Open Source or Peter Graf,
21  please see: http://www.mission-base.com/.
22 
23  The mOrientation code is derived from
24 
25  package com.epichorns.compass3D;
26 
27  found on stackoverflow, see answer to
28 
29  http://stackoverflow.com/questions/10192057/android-getorientation-method-returns-bad-results
30 
31  by user epichorns, see
32 
33  http://stackoverflow.com/users/1350375/epichorns
34  */
35 
36 package com.mission_base.arviewer_android.viewer;
37 
38 import android.content.Context;
39 import android.graphics.Canvas;
40 import android.graphics.Paint;
41 import android.graphics.Paint.Style;
42 import android.hardware.Sensor;
43 import android.hardware.SensorEvent;
44 import android.hardware.SensorEventListener;
45 import android.hardware.SensorManager;
46 import android.util.Log;
47 import android.view.View;
48 
49 import com.mission_base.arviewer_android.Arvos;
50 import com.mission_base.arviewer_android.viewer.opengl.ArvosObject;
51 
61 public class ArvosRadarView extends View
62 {
63  private Arvos mInstance;
64  private String mTag = "ArvosRadarView";
65  private Paint mPaint = new Paint();
66 
67  private float mAngleFilteredAzimuth = 0;
68  private float mAngleFilteredPitch = 0;
69  private float mAngleFilteredRoll = 0;
70 
71  private SensorManager mSensorManager;
72 
73  // sensor calculation values
74  private float[] mGravity = null;
75  private float[] mGeomagnetic = null;
76  private float Rmat[] = new float[9];
77  private float Imat[] = new float[9];
78  private float mOrientation[] = new float[3];
79 
86  public ArvosRadarView(Context context)
87  {
88  super(context);
89  Log.d(mTag, "ArvosRadarView()");
90 
91  mInstance = Arvos.getInstance();
92  mPaint.setColor(0xff0000ff);
93  mPaint.setStyle(Style.STROKE);
94  mPaint.setAntiAlias(true);
95 
96  mSensorManager = (SensorManager) mInstance.getActivity().getSystemService(Context.SENSOR_SERVICE);
97  mSensorManager.registerListener(mAccelerometerListener, mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_UI);
98  mSensorManager.registerListener(mMagnetometerListener, mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD), SensorManager.SENSOR_DELAY_UI);
99  update();
100  }
101 
102  SensorEventListener mAccelerometerListener = new SensorEventListener()
103  {
104  public void onAccuracyChanged(Sensor sensor, int accuracy)
105  {
106  }
107 
108  public void onSensorChanged(SensorEvent event)
109  {
110  if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER)
111  {
112  mGravity = event.values.clone();
113  processSensorData();
114  update();
115  }
116  }
117  };
118  SensorEventListener mMagnetometerListener = new SensorEventListener()
119  {
120  public void onAccuracyChanged(Sensor sensor, int accuracy)
121  {
122  }
123 
124  public void onSensorChanged(SensorEvent event)
125  {
126  if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD)
127  {
128  mGeomagnetic = event.values.clone();
129  processSensorData();
130  update();
131  }
132  }
133  };
134 
135  private float restrictAngle(float angle)
136  {
137  while (angle >= 180)
138  {
139  angle -= 360;
140  }
141  while (angle < -180)
142  {
143  angle += 360;
144  }
145  return angle;
146  }
147 
148  // x is a raw angle value from getOrientation(...)
149  // y is the current filtered angle value
150  private float calculateFilteredAngle(float x, float y)
151  {
152  final float alpha = 0.3f;
153  float diff = x - y;
154 
155  // here, we ensure that abs(diff)<=180
156  diff = restrictAngle(diff);
157 
158  // ensure that y stays within [-180, 180[ bounds
159  y = restrictAngle(y + alpha * diff);
160 
161  return y;
162  }
163 
164  private void processSensorData()
165  {
166  if (mGravity != null && mGeomagnetic != null)
167  {
168  boolean success = SensorManager.getRotationMatrix(Rmat, Imat, mGravity, mGeomagnetic);
169  if (success)
170  {
171  SensorManager.getOrientation(Rmat, mOrientation);
172  mAngleFilteredAzimuth = calculateFilteredAngle(Arvos.toDegrees(mOrientation[0]), mAngleFilteredAzimuth);
173  mAngleFilteredPitch = calculateFilteredAngle(Arvos.toDegrees(mOrientation[1]), mAngleFilteredPitch);
174  mAngleFilteredRoll = calculateFilteredAngle(-Arvos.toDegrees(mOrientation[2]), mAngleFilteredRoll);
175  }
176  mGravity = null; // full new refresh
177  mGeomagnetic = null;
178  }
179  }
180 
181  private void update()
182  {
183  mInstance.mAzimuth = mAngleFilteredAzimuth;
184  mInstance.mPitch = mAngleFilteredPitch;
185  mInstance.mRoll = mAngleFilteredRoll;
186 
187  this.invalidate();
188  ArvosTextView textView = ((ArvosViewer) (mInstance.getActivity())).mTextView;
189  if (textView != null)
190  {
191  textView.updateWithNewLocation();
192  }
193  }
194 
198  protected void onDraw(Canvas canvas)
199  {
200  int width = getWidth();
201  int centerX = width - 100;
202  int centerY = 100;
203 
204  float degrees = mInstance.mCorrectedAzimuth;
205 
206  mPaint.setColor(0xffff0000);
207  mPaint.setStrokeWidth(2);
208  synchronized (mInstance.mArvosObjects)
209  {
210  for (ArvosObject arvosObject : mInstance.mArvosObjects)
211  {
212  int x = Math.round(arvosObject.mPosition[0]);
213  int y = Math.round(arvosObject.mPosition[2]);
214 
215  double distance = Math.sqrt(x * x + y * y);
216  if (distance < 99)
217  {
218  x += centerX;
219  y += centerY;
220  canvas.drawLine(x - 3, y - 3, x + 3, y + 3, mPaint);
221  canvas.drawLine(x + 3, y - 3, x - 3, y + 3, mPaint);
222  }
223  }
224  }
225  mPaint.setColor(0xff0000ff);
226 
227  canvas.rotate(degrees, centerX, centerY);
228 
229  mPaint.setStrokeWidth(4);
230  canvas.drawLine(centerX, centerY, centerX, 0, mPaint);
231  mPaint.setStrokeWidth(8);
232  canvas.drawCircle(centerX, centerY, 50, mPaint);
233  }
234 
235  public void onResume()
236  {
237  mSensorManager.registerListener(mAccelerometerListener, mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_UI);
238  mSensorManager.registerListener(mMagnetometerListener, mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD), SensorManager.SENSOR_DELAY_UI);
239 
240  mAngleFilteredAzimuth = 0;
241  mAngleFilteredPitch = 0;
242  mAngleFilteredRoll = 0;
243 
244  update();
245  }
246 
247  public void onPause()
248  {
249  mSensorManager.unregisterListener(mAccelerometerListener);
250  mSensorManager.unregisterListener(mMagnetometerListener);
251  }
252 }