我有以下代码:
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: How to get accurate altitude?
但我仍然感到困惑。你能指导我如何编写代码吗?值得注意的是,我想基于气压传感器使用它。
答案 0 :(得分:7)
气压计提供压力读数,而非高度压力读数。
现在因为有一个渐变的压力,一般来说它会随着海拔的升高而降低,理论上你可以从压力差来推断出海拔高度的差异。这就是你所知道的非校准高度计:你不知道你当前的高度,但你会知道你何时爬升或下降以及多少。
要根据当前压力计算高度,您需要一个参考压力。例如,您需要知道海平面的压力。因此,如果在海平面上的压力为x hPa,并且气压计读数为x + 3 hPa,并且您知道压力每米增加+ 1hPa,则您的海拔高度将为海拔3米。
问题是任何参考压力都会因气象现象而变化。所以它只会在某个区域有效。机场为飞机提供此信息,以便他们可以使用正确的参考压力设置其高度计(例如,QNH)。一旦你知道这个参考压力归一化到海平面(QNH不是,你最好使用QFF),你可以将它作为第一个参数传递给这个方法:
SensorManager.getAltitude(<reference pressure at sea level>, pressure_value);
请记住,您无法对参考压力进行硬编码。它像温度一样不断变化。您需要在互联网上查找,或使用航空气象服务。
答案 1 :(得分:4)
昼夜温度的变化会导致气压差异,这也是您获得不同高度读数的原因。如果您可以考虑温度的影响,则可以纠正错误。
答案 2 :(得分:3)
气压传感器测量来自色谱柱的压力 传感器上方的空气 - 它不测量高于地面的高度。 幸运的是,存在(大多数)直接相关性。但是,空气 压缩和膨胀,柱子施加的压力不是 不变。压力和海拔之间的相关性需要 校正了空气密度的局部变化。这种修正是 飞机飞行员非常感兴趣,所以政府确定 每个机场都可以免费提供这些信息。
因为温度和气压是随机变化的 所有的时间,所以最准确的你需要知道 您当地的当前标准压力。
您可以先获取最近的气压计值 机场,然后使用该值而不是PRESSURE_STANDARD_ATMOSPHERE。 您需要知道工作站ID,或指定纬度/长矩形。 请参阅METAR station specifications。
但是 ...如果您当前的错误只有2米,那已经是 很好。你永远不会从气压计得到精确的高度 高度计 - 这就是发明雷达高度计的原因。
http://www.aviationweather.gov/adds/dataserver_current/httpparam?dataSource=metars&requestType=retrieve&format=xml&stationString=KSFO&hoursBeforeNow=1&mostRecent=true
这将返回KSFO(旧金山)的最新METAR:
<?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。
这是一个显示当前气压的片段 您当前位置的地图。
我开始写&#34;对&#34;代码来解析XML,但失去了兴趣 当我不得不走下节点。我把它留作学习练习 并写了&#34; hack&#34;而不是版本。
/***********************************************************************/
/** 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>