blob: 23012bd844f94650cc95e29413885e7bd2ddb4ef [file] [log] [blame]
/*
* Copyright 2012 AndroidPlot.com
*
* 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.androidplot.demos;
import android.app.Activity;
import android.content.Context;
import android.graphics.Color;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.view.View;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import com.androidplot.Plot;
import com.androidplot.util.PlotStatistics;
import com.androidplot.util.Redrawer;
import com.androidplot.xy.*;
import java.text.DecimalFormat;
import java.util.Arrays;
// Monitor the phone's orientation sensor and plot the resulting azimuth pitch and roll values.
// See: http://developer.android.com/reference/android/hardware/SensorEvent.html
public class OrientationSensorExampleActivity extends Activity implements SensorEventListener
{
private static final int HISTORY_SIZE = 300; // number of points to plot in history
private SensorManager sensorMgr = null;
private Sensor orSensor = null;
private XYPlot aprLevelsPlot = null;
private XYPlot aprHistoryPlot = null;
private CheckBox hwAcceleratedCb;
private CheckBox showFpsCb;
//private SimpleXYSeries aprLevelsSeries = null;
private SimpleXYSeries aLvlSeries;
private SimpleXYSeries pLvlSeries;
private SimpleXYSeries rLvlSeries;
private SimpleXYSeries azimuthHistorySeries = null;
private SimpleXYSeries pitchHistorySeries = null;
private SimpleXYSeries rollHistorySeries = null;
private Redrawer redrawer;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.orientation_sensor_example);
// setup the APR Levels plot:
aprLevelsPlot = (XYPlot) findViewById(R.id.aprLevelsPlot);
aprLevelsPlot.setDomainBoundaries(-1, 1, BoundaryMode.FIXED);
aprLevelsPlot.getGraphWidget().getDomainLabelPaint().setColor(Color.TRANSPARENT);
aLvlSeries = new SimpleXYSeries("A");
pLvlSeries = new SimpleXYSeries("P");
rLvlSeries = new SimpleXYSeries("R");
aprLevelsPlot.addSeries(aLvlSeries,
new BarFormatter(Color.rgb(0, 200, 0), Color.rgb(0, 80, 0)));
aprLevelsPlot.addSeries(pLvlSeries,
new BarFormatter(Color.rgb(200, 0, 0), Color.rgb(0, 80, 0)));
aprLevelsPlot.addSeries(rLvlSeries,
new BarFormatter(Color.rgb(0, 0, 200), Color.rgb(0, 80, 0)));
aprLevelsPlot.setDomainStepValue(3);
aprLevelsPlot.setTicksPerRangeLabel(3);
// per the android documentation, the minimum and maximum readings we can get from
// any of the orientation sensors is -180 and 359 respectively so we will fix our plot's
// boundaries to those values. If we did not do this, the plot would auto-range which
// can be visually confusing in the case of dynamic plots.
aprLevelsPlot.setRangeBoundaries(-180, 359, BoundaryMode.FIXED);
// update our domain and range axis labels:
aprLevelsPlot.setDomainLabel("");
aprLevelsPlot.getDomainLabelWidget().pack();
aprLevelsPlot.setRangeLabel("Angle (Degs)");
aprLevelsPlot.getRangeLabelWidget().pack();
aprLevelsPlot.setGridPadding(15, 0, 15, 0);
aprLevelsPlot.setRangeValueFormat(new DecimalFormat("#"));
// setup the APR History plot:
aprHistoryPlot = (XYPlot) findViewById(R.id.aprHistoryPlot);
azimuthHistorySeries = new SimpleXYSeries("Az.");
azimuthHistorySeries.useImplicitXVals();
pitchHistorySeries = new SimpleXYSeries("Pitch");
pitchHistorySeries.useImplicitXVals();
rollHistorySeries = new SimpleXYSeries("Roll");
rollHistorySeries.useImplicitXVals();
aprHistoryPlot.setRangeBoundaries(-180, 359, BoundaryMode.FIXED);
aprHistoryPlot.setDomainBoundaries(0, HISTORY_SIZE, BoundaryMode.FIXED);
aprHistoryPlot.addSeries(azimuthHistorySeries,
new LineAndPointFormatter(
Color.rgb(100, 100, 200), null, null, null));
aprHistoryPlot.addSeries(pitchHistorySeries,
new LineAndPointFormatter(
Color.rgb(100, 200, 100), null, null, null));
aprHistoryPlot.addSeries(rollHistorySeries,
new LineAndPointFormatter(
Color.rgb(200, 100, 100), null, null, null));
aprHistoryPlot.setDomainStepMode(XYStepMode.INCREMENT_BY_VAL);
aprHistoryPlot.setDomainStepValue(HISTORY_SIZE/10);
aprHistoryPlot.setTicksPerRangeLabel(3);
aprHistoryPlot.setDomainLabel("Sample Index");
aprHistoryPlot.getDomainLabelWidget().pack();
aprHistoryPlot.setRangeLabel("Angle (Degs)");
aprHistoryPlot.getRangeLabelWidget().pack();
aprHistoryPlot.setRangeValueFormat(new DecimalFormat("#"));
aprHistoryPlot.setDomainValueFormat(new DecimalFormat("#"));
// setup checkboxes:
hwAcceleratedCb = (CheckBox) findViewById(R.id.hwAccelerationCb);
final PlotStatistics levelStats = new PlotStatistics(1000, false);
final PlotStatistics histStats = new PlotStatistics(1000, false);
aprLevelsPlot.addListener(levelStats);
aprHistoryPlot.addListener(histStats);
hwAcceleratedCb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
if(b) {
aprLevelsPlot.setLayerType(View.LAYER_TYPE_NONE, null);
aprHistoryPlot.setLayerType(View.LAYER_TYPE_NONE, null);
} else {
aprLevelsPlot.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
aprHistoryPlot.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}
}
});
showFpsCb = (CheckBox) findViewById(R.id.showFpsCb);
showFpsCb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
levelStats.setAnnotatePlotEnabled(b);
histStats.setAnnotatePlotEnabled(b);
}
});
// get a ref to the BarRenderer so we can make some changes to it:
BarRenderer barRenderer = (BarRenderer) aprLevelsPlot.getRenderer(BarRenderer.class);
if(barRenderer != null) {
// make our bars a little thicker than the default so they can be seen better:
barRenderer.setBarWidth(25);
}
// register for orientation sensor events:
sensorMgr = (SensorManager) getApplicationContext().getSystemService(Context.SENSOR_SERVICE);
for (Sensor sensor : sensorMgr.getSensorList(Sensor.TYPE_ORIENTATION)) {
if (sensor.getType() == Sensor.TYPE_ORIENTATION) {
orSensor = sensor;
}
}
// if we can't access the orientation sensor then exit:
if (orSensor == null) {
System.out.println("Failed to attach to orSensor.");
cleanup();
}
sensorMgr.registerListener(this, orSensor, SensorManager.SENSOR_DELAY_UI);
redrawer = new Redrawer(
Arrays.asList(new Plot[]{aprHistoryPlot, aprLevelsPlot}),
100, false);
}
@Override
public void onResume() {
super.onResume();
redrawer.start();
}
@Override
public void onPause() {
redrawer.pause();
super.onPause();
}
@Override
public void onDestroy() {
redrawer.finish();
super.onDestroy();
}
private void cleanup() {
// aunregister with the orientation sensor before exiting:
sensorMgr.unregisterListener(this);
finish();
}
// Called whenever a new orSensor reading is taken.
@Override
public synchronized void onSensorChanged(SensorEvent sensorEvent) {
// update level data:
aLvlSeries.setModel(Arrays.asList(
new Number[]{sensorEvent.values[0]}),
SimpleXYSeries.ArrayFormat.Y_VALS_ONLY);
pLvlSeries.setModel(Arrays.asList(
new Number[]{sensorEvent.values[1]}),
SimpleXYSeries.ArrayFormat.Y_VALS_ONLY);
rLvlSeries.setModel(Arrays.asList(
new Number[]{sensorEvent.values[2]}),
SimpleXYSeries.ArrayFormat.Y_VALS_ONLY);
// get rid the oldest sample in history:
if (rollHistorySeries.size() > HISTORY_SIZE) {
rollHistorySeries.removeFirst();
pitchHistorySeries.removeFirst();
azimuthHistorySeries.removeFirst();
}
// add the latest history sample:
azimuthHistorySeries.addLast(null, sensorEvent.values[0]);
pitchHistorySeries.addLast(null, sensorEvent.values[1]);
rollHistorySeries.addLast(null, sensorEvent.values[2]);
}
@Override
public void onAccuracyChanged(Sensor sensor, int i) {
// Not interested in this event
}
}