为什么如果是晚上或晚上高度会发生变化?

时间:2015-07-29 04:12:33

标签: android sensormanager altitude

我有以下代码:

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?

但我仍然感到困惑。你能指导我如何编写代码吗?值得注意的是,我想基于气压传感器使用它。

3 个答案:

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