Why does altitude change if it is evening or night?

I have the following code:

public SensorEventListener sensorEventListener = new SensorEventListener() { @Override public void onSensorChanged(SensorEvent event) { float pressure_value = 0.0f; float height = 0.0f; if (Sensor.TYPE_PRESSURE == event.sensor.getType()) { pressure_value = event.values[0]; height = SensorManager.getAltitude(SensorManager.PRESSURE_STANDARD_ATMOSPHERE, pressure_value); } value = String.valueOf(height); } @Override public void onAccuracyChanged(Sensor sensor, int accuracy) { } }; 

I have a height meter, for example 43, xxxxxxx, at 09.AM.

And I checked it again at 09.PM, the result is changing. It changes by 2 meters or more.

Is it because the pressure has changed by the moon or something else?

And how to fix it?

I read the following stream: Android: How to get the exact height?

But I'm still confused. Could you advise me how to write code? And for the record, I want to use it based on a barometric sensor.

+6
source share
3 answers

Barometers provide pressure readings, not altitude.

Now, because there is a pressure gradient, and generally it decreases with height, theoretically you can determine the difference in height from the difference in pressure. This is all that you know with an uncalibrated altimeter: you do not know your current altitude, but you know when you will rise or descend and how much.

To calculate the height from the current pressure, you will need a reference pressure. For example, you need to know what pressure is at sea level. Therefore, if at sea level the pressure is x GPa, and your barometer reads x + 3 hPa, and you know that the pressure increases + 1hPa per meter, your height will be 3 m above sea level.

The problem is that any reference pressure will always change due to meteorological phenomena. Thus, it will only work for a certain time in a certain area. Airports provide this information to aircraft so that they can set their altimeters with the correct reference pressure (e.g. QNH ). Once you know that this normal pressure is normalized to sea level (no QNH, you better use QFF ), you can pass it as the first parameter to this method:

 SensorManager.getAltitude(<reference pressure at sea level>, pressure_value); 

And remember that you cannot tightly support the pressure. It is constantly changing like temperature. You need to search it online or use aeronautical meteorological services.

+7
source

A change in temperature between day and night leads to a difference in air pressure, and for this reason you get different altitude readings. If you can consider the effect of temperature, the error can be corrected.

+4
source

The barometric pressure sensor measures the pressure from the air column above the sensor - it does not measure height above ground. Fortunately, there is a (mostly) direct correlation. However, the air is compressed and expanded, and the pressure exerted by the column is not constant. The correlation between pressure and height should be adjusted for this local change in air density. This correction is of great interest to aircraft pilots, so the government is confident that each airport makes this information freely available.

Since temperature and barometric pressure vary randomly all the time, therefore, to be most accurate, you need to know the current standard pressure in your area.

You can first select the current barometer value for the nearest airport, then use this value instead of PRESSURE_STANDARD_ATMOSPHERE. You will need to find out the station identifier or specify the lat / long rectangle. See the technical specifications of the METAR station .

BUT ... If your current error is only 2 meters, this is already excellent. You will never get the exact height from a barometric altimeter - that's why radar altimeters were invented.

 http://www.aviationweather.gov/adds/dataserver_current/httpparam?dataSource=metars&requestType=retrieve&format=xml&stationString=KSFO&hoursBeforeNow=1&mostRecent=true 

This returns the most recent METAR for KSFO (San Francisco):

 <?xml version="1.0" encoding="UTF-8"?> <response xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XML-Schema-instance" version="1.2" xsi:noNamespaceSchemaLocation="http://aviationweather.gov/adds/schema/metar1_2.xsd"> <request_index>34600121</request_index> <data_source name="metars" /> <request type="retrieve" /> <errors /> <warnings /> <time_taken_ms>1</time_taken_ms> <data num_results="1"> <METAR> <raw_text>KSFO 061756Z 30011KT 10SM FEW008 BKN160 19/13 A2992 RMK AO2 SLP132 T01890133 10189 20150 51006</raw_text> <station_id>KSFO</station_id> <observation_time>2015-08-06T17:56:00Z</observation_time> <latitude>37.62</latitude> <longitude>-122.37</longitude> <temp_c>18.9</temp_c> <dewpoint_c>13.3</dewpoint_c> <wind_dir_degrees>300</wind_dir_degrees> <wind_speed_kt>11</wind_speed_kt> <visibility_statute_mi>10.0</visibility_statute_mi> <altim_in_hg>29.920275</altim_in_hg> <sea_level_pressure_mb>1013.2</sea_level_pressure_mb> <quality_control_flags> <auto_station>TRUE</auto_station> </quality_control_flags> <sky_condition sky_cover="FEW" cloud_base_ft_agl="800" /> <sky_condition sky_cover="BKN" cloud_base_ft_agl="16000" /> <flight_category>VFR</flight_category> <three_hr_pressure_tendency_mb>0.6</three_hr_pressure_tendency_mb> <maxT_c>18.9</maxT_c> <minT_c>15.0</minT_c> <metar_type>SPECI</metar_type> <elevation_m>3.0</elevation_m> </METAR> </data> </response> 

You want to display the value sea_level_pressure_mb , which is 1013.2.

Here is a snippet that displays the current barometric pressure on a map of your current location.

I started writing the "right" code for XML parsing, but lost interest when I had to go down the nodes. I left this as a training exercise and instead wrote a version of "hack".

 /***********************************************************************/ /** Page2: Simple example of using Google Map. **/ /** TeasingDart **/ /***********************************************************************/ package com.nlited.twopages; import android.app.Activity; import android.location.Criteria; import android.location.Location; import android.location.LocationListener; import android.location.LocationManager; import android.os.Bundle; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import com.google.android.gms.maps.CameraUpdateFactory; import com.google.android.gms.maps.GoogleMap; import com.google.android.gms.maps.MapFragment; import com.google.android.gms.maps.MapView; import com.google.android.gms.maps.model.LatLng; import com.google.android.gms.maps.model.MarkerOptions; import org.w3c.dom.Document; import org.xml.sax.InputSource; import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import java.io.StringReader; import java.net.HttpURLConnection; import java.net.URL; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; public class Page2 extends MapFragment implements LocationListener { private static Page2 mObj; private Activity mActivity; private View mView; private MapView mMapView; private GoogleMap mMap; private LocationManager mLocMgr; private String mLocProvider; private Location mLoc; private LatLng mLatLng= new LatLng(43,-122); private boolean mSlpFound= false; private float mSLP= 1012; private String mStationID; private long mNextSlpCheck= 0; static public Page2 getInstance() { if(mObj==null) mObj= new Page2(); return(mObj); } public Page2() { Debug("constructor %s", this.toString()); mObj= this; } @Override public void onAttach(Activity activity) { Debug("onAttach()"); mActivity= (Main)activity; super.onAttach(activity); startLocation(); new Thread(new GetSLP(),"GetSLP").start(); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle state) { mActivity= (Main)getActivity(); Debug("onCreateView()"); super.onCreateView(inflater, container, state); mView= inflater.inflate(R.layout.frag_page2, container, false); mMapView= (MapView)mView.findViewById(R.id.map); mMapView.onCreate(state); mMapView.onResume(); mMap= mMapView.getMap(); mapUpdate(); return(mView); } /***********************************************************************/ /** Update the map using my GPS location and current SLP. **/ /***********************************************************************/ private void mapUpdate() { MarkerOptions opt = new MarkerOptions(); if(mMap!=null) { String status= mSlpFound ? String.format("%.1f %s",mSLP,mStationID) : "????"; mMap.clear(); mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(mLatLng, 15)); mMap.addMarker(opt.position(mLatLng).title(status)); } } /***********************************************************************/ /** Retrieve my current GPS location. **/ /***********************************************************************/ private void startLocation() { mLocMgr= (LocationManager)mActivity.getSystemService(Activity.LOCATION_SERVICE); if(mLocMgr==null) { Debug("Location services are not available."); } else if(!mLocMgr.isProviderEnabled(LocationManager.GPS_PROVIDER)) { Debug("GPS is not enabled."); } else { mLocProvider= mLocMgr.getBestProvider(new Criteria(),false); if(mLocProvider==null) { Debug("No GPS providers available."); } else { mLoc = mLocMgr.getLastKnownLocation(mLocProvider); mLocMgr.requestLocationUpdates(mLocProvider,30000,1,this); } } } @Override public void onLocationChanged(Location loc) { Debug("Updated location: %f %f",loc.getLatitude(),loc.getLongitude()); mLoc= loc; mLatLng= new LatLng(mLoc.getLatitude(), mLoc.getLongitude()); if(System.currentTimeMillis() >= mNextSlpCheck) new Thread(new GetSLP(),"GetSLP").start(); mapUpdate(); } @Override public void onStatusChanged(String provider, int status, Bundle state) { Debug("Location %s state is now %d.",provider,status); if(status>0) mapUpdate(); } @Override public void onProviderEnabled(String provider) { Debug("Location %s is now enabled.",provider); } @Override public void onProviderDisabled(String provider) { Debug("Location %s is now disabled.",provider); } /***********************************************************************/ /** Background task to request the sea level pressure (SLP) from **/ /** the closest reporting station. **/ /***********************************************************************/ private class GetSLP implements Runnable { public void run() { int range; boolean found= false; //Next check in 15 minutes from now. mNextSlpCheck= System.currentTimeMillis()+15*60*1000; for(range=10;range<100;range+=10) { URL url = buildUrl(range); if(url!=null) { String xml = fetch(url); if(xml!=null) { //found= parse(xml); String slp= hack("sea_level_pressure_mb",xml); if(slp!=null) { mSLP= Float.parseFloat(slp); mStationID= hack("station_id", xml); found = true; break; } } } } if(found) { Debug("Station found within %dkm.", range); mSlpFound = true; mActivity.runOnUiThread(new Runnable(){ public void run() { mapUpdate(); } }); } else { Debug("No stations found within 100km!"); } } //Build the request URL using a radial range from the current (longitude,latitude) private URL buildUrl(int range) { URL url= null; String protocol= "http"; String host= "www.aviationweather.gov"; String page= "adds/dataserver_current/httpparam"; String parms= "dataSource=metars&requestType=retrieve&format=xml&hoursBeforeNow=1&mostRecent=true"; parms+= String.format("&radialDistance=%d;%f,%f",range,mLatLng.longitude,mLatLng.latitude); String urlStr= String.format("%s://%s/%s?%s",protocol,host,page,parms); try { url = new URL(urlStr); } catch(Exception ex) { Debug("buildUrl(%s) blew up.", urlStr); } return(url); } //Fetch the most current METARS report as an xml document. private String fetch(URL url) { String text= null; try { HttpURLConnection connect = (HttpURLConnection)url.openConnection(); InputStream strm= connect.getInputStream(); BufferedReader reader= new BufferedReader(new InputStreamReader(strm)); StringBuilder xml= new StringBuilder(); String line; while((line= reader.readLine())!=null) { xml.append(line); } reader.close(); text= xml.toString(); } catch(Exception ex) { Debug("GetSLP.fetch() blew up."); } return(text); } //Quick hack version to extract a value from the xml string. private String hack(String name, String xml) { String value= null; String tag= String.format("<%s>",name); int nStart= xml.indexOf(tag); if(nStart>=0) { int nEnd = xml.indexOf("</", nStart+tag.length()); if(nEnd>nStart) { value = xml.substring(nStart+tag.length(), nEnd); } } return(value); } //The proper (but incomplete) method to parse the xml document. private boolean parse(String xml) { boolean found= false; Float slp= 0.0f; try { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); InputSource src= new InputSource(); src.setCharacterStream(new StringReader(xml)); Document doc = builder.parse(src); //TODO: Walk the nodes down to "sea_level_pressure_mb" //slp= Float.parseFloat(value); //found= true; } catch(Exception ex) { Debug("GetSLP.parse() blew up."); } return(found); } } private void Debug(String fmt, Object... args) { Log.w("2Page:Page2", String.format(fmt, args)); } } //EOF: PAGE2.JAVA 

Markup:

 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" android:paddingBottom="@dimen/activity_vertical_margin" android:background="@color/ForestGreen" tools:context=".Page2" > <TextView android:id="@+id/Page2_Title" android:text="This is Page Two" android:textSize="24pt" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:gravity="center" /> <com.google.android.gms.maps.MapView android:id="@+id/map" android:name="com.google.android.gms.maps.SupportMapFragment" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_below="@+id/Page2_Title" /> </RelativeLayout> 
+3
source

All Articles