Intereting Posts
Android ListActivity нажмите кнопку Как сделать горизонтальную линию в Android программно Должен ли я оставить bluetooth-отражение взлома в производственном коде? Отсутствие взаимного авторизации на Android w / javax.net.ssl.SSLHandshakeException: сообщение об ошибке не выполнено Android: предпочтение Programmatic «разрешить переориентацию» работает только один раз Интегрировать созданные Java-классы Java в проект Android Как добавить библиотеку (поддержка android-v7-appcompat) в IntelliJ IDEA Загрузить изображение с камеры в ImageView в фрагменте Попытайтесь понять поведение BottomSheet в библиотеке поддержки Android 23.2.1 Как объединить растровое изображение наложения и захваченное изображение в Android? Как объявить константу, которая видна для файла build.gradle всех модулей? Как перезапустить / обновить содержимое активности при нажатии уведомления Изменить цвет текста простого списка ViewView Множественный выбор Android ArrayAdapter требует, чтобы идентификатор ресурса был TextView в DialogFragment Не открывать навигационный ящик по умолчанию

Почему высота меняется, если это вечер или ночь?

У меня есть следующий код:

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) { } }; 

У меня есть метр высоты, например 43, xxxxxxx, в 09.AM.

И я проверил его снова в 09.PM, результат меняется. Он меняет 2 метра или больше.

Это потому, что давление изменилось луной или чем-то еще?

И как это исправить?

Я прочитал следующий поток: Android: Как получить точную высоту?

Но я все еще запутался. Не могли бы вы посоветовать мне, как писать код? И для заметки, я хочу использовать его на основе барометрического датчика.

Барометры обеспечивают показания давления, а не высотные.

Теперь, потому что есть градиент давления, и в целом он уменьшается с высотой, теоретически вы можете определить разницу в высоте от разницы в давлении. Это все, что вы знаете, с некалиброванным высотомером: вы не знаете свою текущую высоту, но вы будете знать, когда будете подниматься или спускаться и сколько.

Для вычисления высоты от текущего давления вам потребуется опорное давление. Например, вам нужно знать, какое давление находится на уровне моря. Так что, если на уровне моря давление х хПа, а ваш барометр читает х + 3 гПа, и вы знаете, что давление увеличивается + 1hPa на метр, ваша высота будет на 3 м выше уровня моря.

Проблема заключается в том, что любое эталонное давление всегда будет меняться в связи с метеорологическими явлениями. Таким образом, это будет действовать только в течение некоторого времени в определенной области. Аэропорты предоставляют эту информацию для самолетов, чтобы они могли устанавливать свои высотомеры с правильным опорным давлением (например, QNH ). Как только вы узнаете, что это нормальное давление, нормированное на уровень моря (QNH – нет, лучше использовать QFF ), вы можете передать его в качестве первого параметра для этого метода:

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

И помните, что вы не можете жёстко опорное давление. Он постоянно меняется, как температура. Вам нужно искать его в Интернете или использовать авиационные метеорологические службы.

Изменение температуры между днем ​​и ночью приводит к разнице давления воздуха, и именно по этой причине вы получаете разные показания высоты. Если вы можете учитывать влияние температуры, ошибка может быть исправлена.

Датчик барометрического давления измеряет давление от колонки воздуха над датчиком – он не измеряет высоту над землей. К счастью, существует (в основном) прямая корреляция. Однако воздух сжимается и расширяется, а давление, оказываемое колонкой, не является постоянным. Корреляция между давлением и высотой должна быть скорректирована для этого локального изменения плотности воздуха. Эта коррекция представляет большой интерес для пилотов самолетов, поэтому правительство гарантирует, что каждый аэропорт делает эту информацию доступной.

Поскольку температура и барометрическое давление постоянно меняются, поэтому, чтобы быть наиболее точными, вам нужно знать текущее стандартное давление в вашем регионе.

Вы можете сначала получить текущее значение барометра для ближайшего аэропорта, а затем использовать это значение вместо PRESSURE_STANDARD_ATMOSPHERE. Вам нужно будет знать идентификатор станции или указать прямоугольник lat / long. См. Спецификации станции METAR .

НО … Если ваша текущая ошибка составляет всего 2 метра, это уже очень хорошо. Вы никогда не получите точную высоту от барометрического высотомера – именно поэтому были изобретены радиолокационные высотомеры.

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

Это возвращает самый последний METAR для KSFO (Сан-Франциско):

 <?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> 

Вы хотите вывести значение для sea_level_pressure_mb которое равно 1013.2.

Вот фрагмент, который отображает текущее барометрическое давление на карте вашего текущего местоположения.

Я начал писать «правильный» код для анализа XML, но потерял интерес, когда мне пришлось спуститься по узлам. Я оставил это как учебное упражнение и вместо этого написал «взломанную» версию.

 /***********************************************************************/ /** 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 

Планировка:

 <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>