Android Open Source - Flight-Computer-Android-Flightradar24 Pressure Altimeter Activity






From Project

Back to project page Flight-Computer-Android-Flightradar24.

License

The source code is released under:

GNU General Public License

If you think the Android project Flight-Computer-Android-Flightradar24 listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

package com.flightcomputer;
import com.flightcomputer.utilities.KalmanFilter;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.os.SystemClock;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
/*from  www  . j av a2s  .  c o  m*/
public class PressureAltimeterActivity extends Activity implements SensorEventListener {
// A reference to this activity, for use in anonymous classes.
  private PressureAltimeterActivity this_activity_;  
  // Handles for all of the moving parts of the altimeter.
  private ImageView altimeter_needle_100_;
  private ImageView altimeter_needle_1000_;
  private ImageView altimeter_needle_10000_;
  private ImageView altimeter_pressure_dial_;
  private Button Altdec,Altinc,Exit;
  // Handle for the debug text view.
  private TextView debugTextView_;
  
  // Pressure sensor and sensor manager.
  private Sensor sensor_pressure_;
  private SensorManager sensor_manager_;
  
  // Sea level pressure in inches of mercury.
  private double slp_inHg_;
  // Current measured pressure in millibars. It's aviation; you just have to
  // get used to ugly unit combos like this.
  private double pressure_hPa_;
  
  // Kalman filter for smoothing the measured pressure.
  private KalmanFilter pressure_hPa_filter_;
  // Time of the last measurement in seconds since boot; used to compute time
  // since last update so that the Kalman filter can estimate rate of change.
  private double last_measurement_time_;
  
  // Whether we've admonished the user not to use this app for flying planes.
  private boolean admonished_;
  // Whether we've told the user that they need a pressure sensor.
  private boolean pressured_;
  
  // Constants for the altitude calculation.
  // See http://psas.pdx.edu/RocketScience/PressureAltitude_Derived.pdf
  private static final double SLT_K = 288.15;  // Sea level temperature.
  private static final double TLAPSE_K_PER_M = -0.0065;  // Linear temperature atmospheric lapse rate.
  private static final double G_M_PER_S_PER_S = 9.80665;  // Acceleration from gravity.
  private static final double R_J_PER_KG_PER_K = 287.052;  // Specific gas constant for air, US Standard Atmosphere edition.
  
  // Constants for unit conversion.
  private static final double PA_PER_INHG = 3386;  // Pascals per inch of mercury.
  //private static final double FT_PER_M = 3.2808399;  // Feet per meter.
  private static final double FT_PER_M = 1;  // Feet per meter.
  // Constants for the Kalman filter's noise models. These values are bigger
  // than actual noise recovered from data, but that's because that noise
  // looks more Laplacian than anything.
  private static final double KF_VAR_ACCEL = 0.0075;  // Variance of pressure acceleration noise input.
  private static final double KF_VAR_MEASUREMENT = 0.05;  // Variance of pressure measurement noise.
  
  // Constants for identifying dialogs.
  private static final int DIALOG_ADMONITION = 0;  // Don't use this to fly!
  private static final int DIALOG_PRESSURE = 1;  // Need a pressure sensor.
  private boolean touchinc=false,touchdec=false;
    /** Create activity, init objects, and get handles to various Droidly bits. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);       
        // Set the main layout as the content view.
        setContentView(R.layout.altimeter);
        this.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
        // Create our Kalman filter.
        pressure_hPa_filter_ = new KalmanFilter(KF_VAR_ACCEL);       
        Bundle extras = getIntent().getExtras();
        if (extras != null) {
            String value = extras.getString("slp_inHg_");
            if (value.length() != 0)        
      {
        slp_inHg_=Double.parseDouble(value);            
      }
        }  
        // Obtain handles for all of the moving parts of the altimeter.
        altimeter_needle_100_ = (ImageView) findViewById(R.id.altimeter_needle_100);
        altimeter_needle_1000_ = (ImageView) findViewById(R.id.altimeter_needle_1000);
        altimeter_needle_10000_ = (ImageView) findViewById(R.id.altimeter_needle_10000);
        altimeter_pressure_dial_ = (ImageView) findViewById(R.id.altimeter_pressure_dial);
        
        // Obtain handle for the debug text view.
        debugTextView_ = (TextView) findViewById(R.id.debugText);

        // Obtain sensor manager and pressure sensor.
        sensor_manager_ = (SensorManager) getSystemService(SENSOR_SERVICE);
        sensor_pressure_ = sensor_manager_.getDefaultSensor(Sensor.TYPE_PRESSURE);
        debugTextView_.setVisibility(View.VISIBLE);
        
        Exit = (Button) findViewById(R.id.exit);
        Exit.setOnClickListener(new OnClickListener() {
      @Override
      public void onClick(View view) {  
        Intent intent = new Intent();
           intent.putExtra("slp_inHg_", String.valueOf(slp_inHg_));
           setResult(RESULT_OK, intent);
           finish();
      }
     }            
        );
        Altdec = (Button) findViewById(R.id.decalt);
        Altdec.setOnTouchListener(
            new Button.OnTouchListener() {
              public boolean onTouch(View v, MotionEvent m) {                
                if(m.getAction() == MotionEvent.ACTION_UP){
                  touchdec = false;
                      }else if(m.getAction() == MotionEvent.ACTION_DOWN){
                        touchdec = true;
                      } 
                  return true;
              }
            }
            
        );
        Altinc = (Button) findViewById(R.id.incalt);
        Altinc.setOnTouchListener(
            new Button.OnTouchListener() {
              public boolean onTouch(View v, MotionEvent m) {                
                if(m.getAction() == MotionEvent.ACTION_UP){
                  touchinc = false;
                      }else if(m.getAction() == MotionEvent.ACTION_DOWN){
                        touchinc = true;
                      } 
                  return true;
              }
            }
            
        );
    }  
    /** On resume, set up the display and start listening to the pressure sensor. */
    @Override
    public void onResume() {
      super.onResume();
      
      // Update our self-reference.
      this_activity_ = this;     
  
      // If we have started for the first time or have restored from corrupt
      // state information, the altimeter setting will be bogus. Fall back
      // on the standard day.
        if (slp_inHg_ < 28.1 || slp_inHg_ > 31.0) slp_inHg_ = 29.92;
        
        // Likewise, we set the pressure reading to standard day sea level. It
        // should get overwritten by the sensor right away, but if we don't
        // have a pressure sensor, a nice zero indication will show up instead.
        pressure_hPa_ = 1013.0912;
      
        // We reset the Kalman filter with that same pressure value, then mark
        // now as the time of the last measurement.
        pressure_hPa_filter_.reset(pressure_hPa_);
        last_measurement_time_ = SystemClock.elapsedRealtime() / 1000.;
        
      // Immediately update the hands and the pressure dial to reflect
      // initial or saved state.
        updatePressureDial();
        updateNeedles();      
      
      // Start listening to the pressure sensor.
      if (sensor_pressure_ != null) {
        sensor_manager_.registerListener(this, sensor_pressure_, SensorManager.SENSOR_DELAY_GAME);
      } else if (!pressured_) {
        showDialog(DIALOG_PRESSURE);
        pressured_ = true;
      }      
    }

    /** On pause, stop listening to sensors. */
    @Override
    public void onPause() {
      super.onPause();
      sensor_manager_.unregisterListener(this);
    }
    
    /** Save the current altimeter setting, etc. during interruptions. */
    protected void onSaveInstanceState(Bundle bundle) {
      super.onSaveInstanceState(bundle);
      bundle.putDouble("slp_inHg", slp_inHg_);
      bundle.putBoolean("admonished", admonished_);
      bundle.putBoolean("pressured", pressured_);
    }
    
    /** Retrieve the current altimeter setting, etc. after interruptions. */
    protected void onRestoreInstanceState(Bundle bundle) {
      super.onRestoreInstanceState(bundle);
      slp_inHg_ = bundle.getDouble("slp_inHg");
      admonished_ = bundle.getBoolean("admonished");
      pressured_ = bundle.getBoolean("pressured");
    }

   
    public boolean onKeyDown(int key_code, KeyEvent key_event) {
      if (key_code == KeyEvent.KEYCODE_BACK) {
        Intent intent = new Intent();
         intent.putExtra("slp_inHg_", String.valueOf(slp_inHg_));
         setResult(RESULT_OK, intent);
         finish();
      return true;
    }      
      return true;
    }
   
  public void onAccuracyChanged(Sensor arg0, int arg1) {
    // Does nothing, bummer.
  }

  public void onSensorChanged(SensorEvent event) {
    if(touchinc == true){
      long slp_inHg_long = Math.round(100.0 * slp_inHg_);
      if (slp_inHg_long < 3100) ++slp_inHg_long;  
        slp_inHg_ = slp_inHg_long / 100.0;
        updatePressureDial();
        updateNeedles();  
        }else if(touchdec == true)
        {
          long slp_inHg_long = Math.round(100.0 * slp_inHg_);
      if (slp_inHg_long > 2810) --slp_inHg_long;   
        slp_inHg_ = slp_inHg_long / 100.0;              
        updatePressureDial();
        updateNeedles();
        }
    // Update current measured pressure.
    if (event.sensor.getType() != Sensor.TYPE_PRESSURE) return;  // Should not occur.
    pressure_hPa_ = event.values[0];
    // Update the Kalman filter.
    final double curr_measurement_time = SystemClock.elapsedRealtime() / 1000.;
    final double dt = curr_measurement_time - last_measurement_time_;
        pressure_hPa_filter_.update(pressure_hPa_, KF_VAR_MEASUREMENT, dt);
    last_measurement_time_ = curr_measurement_time;
    // Update the needles.
    updateNeedles();
  }
   private static double hPaToFeet(double slp_inHg, double pressure_hPa) {
      // Algebraically unoptimized computations---let the compiler sort it out.
      double factor_m = SLT_K / TLAPSE_K_PER_M;
      double exponent = -TLAPSE_K_PER_M * R_J_PER_KG_PER_K / G_M_PER_S_PER_S;      
      double current_sea_level_pressure_Pa = slp_inHg * PA_PER_INHG;
      double altitude_m =
          factor_m *
          (Math.pow(100.0 * pressure_hPa / current_sea_level_pressure_Pa, exponent) - 1.0);
      return FT_PER_M * altitude_m;
    }
  
  // Retrieve the fractional part of a double.
  private static double getFractional(double value) {
    return value - ((long) value);
  }
  
  /** Update the positions of the altimeter's three indicator needles to
   *  the current altitude in feet. */
  private void updateNeedles() {
    // Compute current altitude in feet given Kalman-filtered pressure.
    double altitude_ft = hPaToFeet(slp_inHg_, pressure_hPa_filter_.getXAbs());

    // Determine angular orientation of the needles.
    double angle_needle_100 = 360.0 * getFractional(altitude_ft / 1000.0);
    double angle_needle_1000 = 360.0 * getFractional(altitude_ft / 10000.0);
    double angle_needle_10000 = 360.0 * getFractional(altitude_ft / 100000.0);
    
    // Set angular orientation of the needles.
    altimeter_needle_100_.setRotation((float) angle_needle_100);
    altimeter_needle_1000_.setRotation((float) angle_needle_1000);
    altimeter_needle_10000_.setRotation((float) angle_needle_10000);
    
    // Update debugging text.
    // TODO: only if visible
    if (debugTextView_.getVisibility() == View.VISIBLE) {
      debugTextView_.setText(String.format(
          "Altitude: %4.1f m\n" + "Raw baro: %4.3f hPa (mb)\n" + "Filtered: %4.3f hPa (mb)\n"  ,
          hPaToMeter(slp_inHg_,pressure_hPa_filter_.getXAbs()),
          pressure_hPa_,
          pressure_hPa_filter_.getXAbs()));
    }
  }
   private static double hPaToMeter(double slp_inHg, double pressure_hPa) {
        // Algebraically unoptimized computations---let the compiler sort it out.
        double factor_m = SLT_K / TLAPSE_K_PER_M;
        double exponent = -TLAPSE_K_PER_M * R_J_PER_KG_PER_K / G_M_PER_S_PER_S;      
        double current_sea_level_pressure_Pa = slp_inHg * PA_PER_INHG;
        double altitude_m =
            factor_m *
            (Math.pow(100.0 * pressure_hPa / current_sea_level_pressure_Pa, exponent) - 1.0);
        return altitude_m;
      }
  /** Rotate the pressure setting dial to reflect the actual value of slp_inHg_. */
  private void updatePressureDial() {
      double degrees = 100.0 * (31.0 - slp_inHg_);
      altimeter_pressure_dial_.setRotation((float) degrees);
  }
  
  /** Create dialogs, mainly to admonish and pressure the user. */
  protected Dialog onCreateDialog(int id) {
    Dialog dialog;
    switch(id) {
    case DIALOG_PRESSURE: {
      AlertDialog.Builder builder = new AlertDialog.Builder(this);
      builder.setMessage(R.string.alert_pressure)
             .setCancelable(false)
             .setPositiveButton(R.string.alert_pressure_ack, new DialogInterface.OnClickListener() {
               public void onClick(DialogInterface dialog, int id) {
                 dialog.dismiss();
               }
             })
           .setNegativeButton(R.string.alert_pressure_abort, new DialogInterface.OnClickListener() {
               public void onClick(DialogInterface dialog, int id) {
                 this_activity_.finish();
               }
             });
      dialog = builder.create();
      break;
    }
      default:
        dialog = null;
    }
    return dialog;
  }
}




Java Source Code List

com.flightcomputer.Circle.java
com.flightcomputer.DownloadActivity.java
com.flightcomputer.EditPreferences.java
com.flightcomputer.FCActivity.java
com.flightcomputer.GpsSkyActivity.java
com.flightcomputer.IgcLoad.java
com.flightcomputer.LeonardoLiveWriter.java
com.flightcomputer.MapEventListener.java
com.flightcomputer.PositionWriter.java
com.flightcomputer.PressureAltimeterActivity.java
com.flightcomputer.RouteLine.java
com.flightcomputer.Task.java
com.flightcomputer.TrckLine.java
com.flightcomputer.filefilter.FilterByFileExtension.java
com.flightcomputer.filefilter.ValidFileFilter.java
com.flightcomputer.filefilter.ValidMapFile.java
com.flightcomputer.filefilter.ValidRenderTheme.java
com.flightcomputer.filepicker.FilePickerIconAdapter.java
com.flightcomputer.filepicker.FilePicker.java
com.flightcomputer.utilities.BaroService.java
com.flightcomputer.utilities.BeepThread.java
com.flightcomputer.utilities.GpsSkyView.java
com.flightcomputer.utilities.KalmanFilter.java
com.flightcomputer.utilities.PiecewiseLinearFunction.java
com.flightcomputer.utilities.Point2d.java
com.flightcomputer.utilities.VerticalProgressBar_Reverse.java
com.flightcomputer.utilities.VerticalProgressBar.java
com.flightcomputer.openGlUtils.java
com.nutiteq.advancedmap.mapquest.SearchQueryResults.java
com.nutiteq.advancedmap.mapquest.SearchSuggestionProvider.java
com.nutiteq.services.geocode.MapQuestGeocoder.java
com.nutiteq.utils.MapsforgeMapLayer.java
com.nutiteq.utils.MbTilesDatabaseHelper.java
com.nutiteq.utils.MyLocationCircle.java
com.nutiteq.utils.NetUtils.java
com.nutiteq.utils.UiUtils.java
com.nutiteq.utils.UtfGridHelper.java
com.nutiteq.utils.UtfGridLayerInterface.java