Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> android:百度地圖繪制實時路線以及最短線路規劃

android:百度地圖繪制實時路線以及最短線路規劃

編輯:關於Android編程

最近在做百度地圖的實時路線繪制,發現一些問題,比如由於定位漂移帶來的路線繪制偏差,還有由於定位漂移,導致人未走動時,也會繪制路線等。百度鷹眼的線路糾偏個人感覺很一般啊。而且有限漂移了兩百米的點他也沒有糾正過來。所以最後還是決定自己寫一個糾偏吧。而且百度地圖官方的dome和示例代碼真的很示例啊。然人摸不著頭腦。ok進入正題,思路是這樣的,因為實時繪制線路都是在室外,所以只采用gps定位,不采用無線網絡定位。這樣漂移一兩百米的點基本不會出現。第二當人在等紅綠燈時,人是靜止的,但是定位有可能會漂移,所以這部分我們采用手機感應器進行判斷是否移動。ok大體方向確定了,接下來就是進行功能劃分然後開發了。功能模塊主要涉及以下幾點

地圖定位 繪制當前位置 獲取位置進行糾偏 判斷是否移動 繪制線路 線路規劃

程序流程圖凸顯

Created with Rapha?l 2.1.0開始獲取gps位置不是第一個?不是前10個?手機是否處於運動?兩點間距離是否大於1米?兩點間距離是否小於90米?保存位置繪制線路拋棄位置保存位置yesnoyesnoyesnoyesnoyesno

下面是完整代碼

這裡貼出的代碼是基於各位亦有一定百度地圖開發基礎為參照,如果看不懂可留下郵箱我每晚發送源代碼給各位,我是用jar包是3.7.3版的,各位如果使用其他版本的包,可能會出現百度地圖初始化失敗的現象。對我被坑過。

package com.example.baidutext;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.graphics.Color;
import android.hardware.Sensor;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Toast;

import com.baidu.location.BDLocation;
import com.baidu.location.BDLocationListener;
import com.baidu.location.LocationClient;
import com.baidu.location.LocationClientOption;
import com.baidu.mapapi.SDKInitializer;
import com.baidu.mapapi.map.BaiduMap;
import com.baidu.mapapi.map.BaiduMap.OnMapLongClickListener;
import com.baidu.mapapi.map.BitmapDescriptor;
import com.baidu.mapapi.map.BitmapDescriptorFactory;
import com.baidu.mapapi.map.MapStatus;
import com.baidu.mapapi.map.MapStatusUpdate;
import com.baidu.mapapi.map.MapStatusUpdateFactory;
import com.baidu.mapapi.map.MapView;
import com.baidu.mapapi.map.MarkerOptions;
import com.baidu.mapapi.map.OverlayOptions;
import com.baidu.mapapi.map.PolylineOptions;
import com.baidu.mapapi.model.LatLng;
import com.baidu.mapapi.search.route.BikingRouteResult;
import com.baidu.mapapi.search.route.DrivingRouteResult;
import com.baidu.mapapi.search.route.OnGetRoutePlanResultListener;
import com.baidu.mapapi.search.route.PlanNode;
import com.baidu.mapapi.search.route.RoutePlanSearch;
import com.baidu.mapapi.search.route.TransitRouteResult;
import com.baidu.mapapi.search.route.WalkingRoutePlanOption;
import com.baidu.mapapi.search.route.WalkingRouteResult;
import com.baidu.mapapi.utils.DistanceUtil;

public class MainActivity extends Activity {
    /**
     * 百度地圖視圖
     */
    private MapView map_v=null;
    /**
     * 百度地圖管理器
     */
    private BaiduMap BaiDuMap;
    //  /**
    //   * 位置管理器
    //   */
    //  private LocationManager locationManager;
    /**
     * 位置客戶端
     */
    private LocationClient locationClient = null;
    /**
     * 獲取位置時間間隔單位(秒)
     */
    private final int  time= 1000*9;
    //  /**
    //   * 定位數據  
    //   */
    //  private MyLocationData locData;
    /**
     * 構建Marker圖標  
     */
    private BitmapDescriptor bitmap,StartBitmap,EndBitmap;  
    /**
     *判斷是否第一次定位
     */
    private boolean isFirstLoc=true;
    /**
     * 是否處於路線規劃
     */
    private boolean isGetRoute=false;
    /**
     * 是否獲取新路線
     */
    private boolean isGetNewRoute=true;
    /**
     * 定位位置數據
     * 多線程在修改本數據,需要增加一個鎖;
     */
    private List pointList = new ArrayList();
    /**
//   * 判斷是否處於暫停
//   */
    //  private boolean isPause=false;
    /**
     * 描述地圖將要發生的變化
     */
    protected MapStatusUpdate msUpdate = null;
    /**
     *  覆蓋物
     */
    protected OverlayOptions overlay,StartOverlay,EndOverlay;
    /**
     *  路線覆蓋物
     */
    private PolylineOptions polyline = null;
    /**
     * 手機加速度感應器服務注冊
     */
    private SensorManager sm = null;
    private Acc acc=new Acc();
    /**
     * 最大距離單位(米)
     */
    private final Double MaxDistance=90.00;
    /**
     * 最小距離單位(米)
     */
    private final Double MinDistance=2.0;
    /**
     * 電源鎖
     */
    public static WakeLock wakeLock=null;
    private PowerReceiver powerReceiver = new PowerReceiver();
    /**
     *最近位置信息
     */
    private LatLng latLng;
    /**
     * 因距離太大丟失的點數
     */
    private int LostLoc=0;
    /**
     * 第一次定位丟失的點數
     */
    private int FLostLoc=0;
    /**
     * 程序名稱
     */
    private final String APP_FOLDER_NAME = "LocationDemo";
    /**
     * 路線規劃監聽
     */
    private RoutePlanSearch mSearch;
    /**
     * 當前位置,終點位置
     */
    private LatLng ll,EndLL;
    /**
     * 路線規劃等待進度框
     */
    private ProgressDialog progressDialog;
    /**
     * 獲取位置距離常量
     */
    private int constant=0;
    /* (non-Javadoc)
     * @see android.app.Activity#onCreate(android.os.Bundle)
     */
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        sm = (SensorManager) getSystemService(SENSOR_SERVICE);
        SDKInitializer.initialize(getApplicationContext());

//      activityList.add(this);

        setContentView(R.layout.activity_main);
        init();
        //設置定位監聽
        locationClient.registerLocationListener(new BDLocationListener(){

            @Override
            public void onReceiveLocation(BDLocation location) {
                // TODO Auto-generated method stub
                //              locData = new MyLocationData.Builder()  
                //              .accuracy(0)  
                //              // 此處設置開發者獲取到的方向信息,順時針0-360  
                //              .direction(0).latitude(location.getLatitude())  
                //              .longitude(location.getLongitude()).build();  
                //              // 設置定位數據  
                //              BaiDuMap.setMyLocationData(locData);  
                ll = new LatLng(location.getLatitude(),
                        location.getLongitude());
                progressDialog.dismiss();
                if(isFirstLoc||isGetRoute){
                    if(!isGetRoute){
                        MapStatusUpdate u = MapStatusUpdateFactory.newLatLng(ll);
                        BaiDuMap.animateMapStatus(u);
                    }
                    //              MyLocationConfiguration config = new MyLocationConfiguration(LocationMode.NORMAL, true, bitmap);//普通(LocationMode.NORMAL)、跟隨(LocationMode.FOLLOWING)、羅盤(LocationMode.COMPASS)
                    //              BaiDuMap.setMyLocationConfigeration(config);
                    isFirstLoc=false;
                    if(constantDistanceUtil.getDistance(pointList.get(constant+1),ll)){
                            save("距離: "+DistanceUtil.getDistance(pointList.get(constant+1),ll)+" 時間: "+getStringDate()+" 點數: "+constant);
                            if(DistanceUtil.getDistance(pointList.get(constant+1),ll)>100&&isGetNewRoute){
                                IsGetNewRoute();
                            }
                            constant++;
                        }else{
                            save("距離: "+DistanceUtil.getDistance(pointList.get(constant),ll)+" 時間: "+getStringDate()+" 點數: "+constant);
                            if(DistanceUtil.getDistance(pointList.get(constant),ll)>100&&isGetNewRoute){
                                IsGetNewRoute();
                            }
                        }
                    }

                    drawRealtimePoint(ll);
                }else{
                    showRealtimeTrack(location);
                }

            }
        });
        locationClient.start();
        //路線規劃回調
        OnGetRoutePlanResultListener listener = new OnGetRoutePlanResultListener(){

            @Override
            public void onGetBikingRouteResult(BikingRouteResult arg0) {
                // TODO Auto-generated method stub
            }

            @Override
            public void onGetDrivingRouteResult(DrivingRouteResult arg0) {
                // TODO Auto-generated method stub
            }

            @Override
            public void onGetTransitRouteResult(TransitRouteResult arg0) {
                // TODO Auto-generated method stub
            }

            @Override
            public void onGetWalkingRouteResult(WalkingRouteResult WalkingRoute) {
                // TODO Auto-generated method stub
                if(WalkingRoute.getRouteLines()!=null){
                    constant =0;
                    isGetNewRoute=true;
                    for(int i=0;i0)
                pointList.clear();
            if(StartOverlay!=null)
                StartOverlay=null;
            if(EndOverlay!=null)
                EndOverlay=null;
        }
        return super.onMenuItemSelected(featureId, item);

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // TODO Auto-generated method stub
        return super.onCreateOptionsMenu(menu);
    }
    /*
     * 將數據臨時保存到xml文件
     */
    private boolean saveArray() {  
        deleteXML();
        SharedPreferences sp= getSharedPreferences("lat", Context.MODE_APPEND);  
        Editor mEdit1= sp.edit(); 
        mEdit1.remove("Status_size");
        mEdit1.putInt("Status_size",pointList.size());

        for(int i=0;i<pointlist.size();i++) {="" medit1.remove("lat_"="" +="" i);="" medit1.putstring("lat_"="" i,pointlist.get(i).latitude+"");="" medit1.remove("lon_"="" medit1.putstring("lon_"="" i,pointlist.get(i).longitude+"");="" }="" return="" medit1.commit();="" @override="" protected="" void="" onresume()="" todo="" auto-generated="" method="" stub="" super.onresume();="" map_v.onresume();="" sm.registerlistener(acc,="" sensor.type_accelerometer="" ,="" sensormanager.sensor_delay_normal);="" acquirewakelock();="" if(latlng!="null)" drawrealtimepoint(latlng);="" *="" 讀取xml文件存儲數據;="" @param="" mcontext="" loadarray(context="" mcontext)="" sharedpreferences="" msharedpreference1="getSharedPreferences(&quot;lat&quot;," context.mode_private);="" pointlist.clear();="" int="" size="mSharedPreference1.getInt(&quot;Status_size&quot;," 0);="" for(int="" i="0;i=2 && pointList.size() <= 100000) {
            // 添加路線(軌跡)
            polyline = new PolylineOptions().width(10)
                    .color(Color.RED).points(pointList);
        }

        addMarker();

    }
    /*
     * 添加地圖覆蓋物
     */
    protected  void addMarker() {

        if (null != msUpdate) {
            BaiDuMap.setMapStatus(msUpdate);
        }

        // 路線覆蓋物
        if (null != polyline) {
            BaiDuMap.addOverlay(polyline);
        }

        // 實時點覆蓋物
        if (null != overlay) {
            BaiDuMap.addOverlay(overlay);
        }

        //起點覆蓋物
        if (null != StartOverlay) {
            BaiDuMap.addOverlay(StartOverlay);
        }
        // 終點覆蓋物
        if (null != EndOverlay) {
            BaiDuMap.addOverlay(EndOverlay);
        }
    }

    /*
     *@author chenzheng_Java  
     *保存用戶輸入的內容到文件 
     */  
    private void save(String content) {  

        try {  
            /* 根據用戶提供的文件名,以及文件的應用模式,打開一個輸出流.文件不存系統會為你創建一個的, 
             * 至於為什麼這個地方還有FileNotFoundException拋出,我也比較納悶。在Context中是這樣定義的 
             *   public abstract FileOutputStream openFileOutput(String name, int mode) 
             *   throws FileNotFoundException; 
             * openFileOutput(String name, int mode); 
             * 第一個參數,代表文件名稱,注意這裡的文件名稱不能包括任何的/或者/這種分隔符,只能是文件名 
             *          該文件會被保存在/data/data/應用名稱/files/chenzheng_java.txt 
             * 第二個參數,代表文件的操作模式 
             *          MODE_PRIVATE 私有(只能創建它的應用訪問) 重復寫入時會文件覆蓋 
             *          MODE_APPEND  私有   重復寫入時會在文件的末尾進行追加,而不是覆蓋掉原來的文件 
             *          MODE_WORLD_READABLE 公用  可讀 
             *          MODE_WORLD_WRITEABLE 公用 可讀寫 
             *  */  
            content=content+"\n";
            FileOutputStream outputStream = openFileOutput("Log.log",Activity.MODE_APPEND);  
            outputStream.write(content.getBytes());  
            outputStream.flush();  
            outputStream.close();  
        } catch (FileNotFoundException e) {  
            e.printStackTrace();  
        } catch (IOException e) {  
            e.printStackTrace();  
        }  

    }  
    /*
     * 獲取系統時間
     */
    private String getStringDate() {
        Date currentTime = new Date();
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String dateString = formatter.format(currentTime);
        return dateString;
    }

    /*
     * 判斷手機是否在運動
     */
    private boolean IsMove(LatLng latLng,BDLocation location){

        if(pointList.size()>=1){
            Double dis=DistanceUtil.getDistance(pointList.get(pointList.size()-1),latLng);
            //判斷手機是否靜止,如果靜止,判定采集點無效,直接拋棄
            if(!acc.is_Acc&&acc.IsRun){
                acc.IsRun=false;
                return false;
            }
            //判斷是否是第一次定位置,如果是第一次定位並且因為第一次拋棄的位置數量小於10個則判斷兩點間距離大小
            if(FLostLoc<10){
                FLostLoc=FLostLoc+1;
                if(dis>10&&FLostLoc<6){//距離大於十米,而且被拋棄數量少於5個則說明有可能是獲取位置失敗
                    pointList.clear();
                    pointList.add(latLng);//更新位置
                    return false;
                }
                if(dis>0&&dis<10&&FLostLoc>=6)//如果距離在10米內,則表示客戶正在運動,直接跳出
                    FLostLoc=11;
            }
            //根據兩點間距離判斷是否發生定位漂移,如果漂移距離小於MinDistance則拋棄,如果漂移距離大於MaxDistance則取兩點的中間點.
                if(dis<=MinDistance){
                    if((dis<=MinDistance||dis>=MaxDistance)){
                    return false;
                }

                if(LostLoc>=4){
                    Double newlatitude=(latLng.latitude+pointList.get(pointList.size()-1).latitude)/2;
                    Double newlongitude=(latLng.longitude+pointList.get(pointList.size()-1).longitude)/2;
                    latLng = new LatLng(newlatitude, newlongitude);
                }else{
                    LostLoc=LostLoc+1;
                    return false;
                }

            }
            LostLoc=0;//重置丟失點的個數
            //          pointList.add(latLng);
            acc.is_Acc=false;
        }
        pointList.add(latLng);
        return true;
    }
    /*
     * 開始規劃線路
     */
    private void StartRoutePlan() {
        // TODO Auto-generated method stub
        progressDialog.setTitle("路線規劃");
        progressDialog.setMessage("正在規劃路線請稍後。。");
        progressDialog.show();
        if(pointList!=null||pointList.size()>0)
            pointList.clear();
        PlanNode stNode = PlanNode.withLocation(ll);  
        StartOverlay=new MarkerOptions().position(ll)
                .icon(StartBitmap).zIndex(9);

        PlanNode enNode = PlanNode.withLocation(EndLL);
        EndOverlay=new MarkerOptions().position(EndLL)
                .icon(EndBitmap).zIndex(9);
        mSearch.walkingSearch((new WalkingRoutePlanOption())  
                    .from(stNode)  
                    .to(enNode));
        isGetRoute=true;
    }
    /*
     * 獲取新路線
     */
    private void IsGetNewRoute() {
        // TODO Auto-generated method stub
        AlertDialog.Builder builder = new Builder(this);
        builder.setMessage("您已偏移路線,是否重新規劃路線?");
        builder.setTitle("路線偏移");
        builder.setPositiveButton("重新規劃", new OnClickListener() {   
            @Override
            public void onClick(DialogInterface dialog, int which) {
                StartRoutePlan();
                dialog.dismiss();
            }
        });  
        builder.setNegativeButton("按原規劃", new OnClickListener() {   
            @Override
            public void onClick(DialogInterface dialog, int which) {
            dialog.dismiss();
        }
        });
        builder.create().show();
        isGetNewRoute=false;
    }
    /*
     * 申請電源鎖 
     */
    private void acquireWakeLock() {
        if (null == wakeLock) {

            PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);

            wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK | PowerManager.ON_AFTER_RELEASE,getClass().getName());

        }
        IntentFilter filter = new IntentFilter();
        filter.addAction(Intent.ACTION_SCREEN_ON);
        filter.addAction(Intent.ACTION_SCREEN_OFF);
        registerReceiver(powerReceiver, filter);
    }

    /*
     * 釋放電源鎖
     */
    private void releaseWakeLock() {
        unregisterReceiver(powerReceiver);
    }
}

下面PowerReceiver文件的內容

這裡貼出的代碼主要是完成電源鎖的開啟和撤銷

package com.example.baidutext;

import android.annotation.SuppressLint;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;

public class PowerReceiver extends BroadcastReceiver {

    @SuppressLint("Wakelock")
    @Override
    public void onReceive(final Context context, final Intent intent) {
        final String action = intent.getAction();

        //按下電源鍵,關閉屏幕
        if (Intent.ACTION_SCREEN_OFF.equals(action)) {
            System.out.println("screen off,acquire wake lock!");
            if (null != MainActivity.wakeLock && !(MainActivity.wakeLock.isHeld())) {
                MainActivity.wakeLock.acquire();
            }
         //按下電源鍵,打開屏幕  
        } else if (Intent.ACTION_SCREEN_ON.equals(action)) {
            System.out.println("screen on,release wake lock!");
            if (null != MainActivity.wakeLock && MainActivity.wakeLock.isHeld()) {
                MainActivity.wakeLock.release();
            }
        }
    }

}

下面Acc文件的內容

這個文件主要是獲取加速感應器的值,然後通過波峰和波谷的插值,以及兩個波峰之間的時間差來判斷手機是否處於移動。關於詳細的大家可查找計步器原理。一下算法非本人原創,但是一直找不到原創作者,如作者本人看到,可與我聯系

package com.example.baidutext;

import android.hardware.Sensor;
import android.hardware.SensorListener;
/**
 *根據加速度判斷手機是否處於靜止
 * @author Administrator
 *
 */
public class Acc implements SensorListener {
    //  /**
    //   * 手機加速度各方向狀態
    //   */
    //  private float F_Acc_x,F_Acc_y,F_Acc_z;
    //  /**
    //   * 上次獲取狀態時間
    //   */
    //  private long LastUpdateTime;   
    //  /**
    //   * 兩次獲取狀態時間間隔單位(秒)
    //   */
    //  private final int UPTATE_INTERVAL_TIME = 1000*10;   
    //  
    /**
     * 當前傳感器的值
     */
    private float gravityNew = 0;
    /**
     * 上次傳感器的值
     */
    private float gravityOld = 0;
    /**
     * 此次波峰的時間
     */
    private long timeOfThisPeak = 0;
    /**
     * 上次波峰的時間
     */
    private long timeOfLastPeak = 0;
    /**
     * 當前的時間
     */
    private long timeOfNow = 0;;
    /**
     * 波峰值
     */
    private float peakOfWave = 0;
    /**
     * 波谷值
     */
    private float valleyOfWave = 0;
    /**
     * 初始阈值
     */
    private float ThreadValue = (float) 2.0;
    /**
     * 動態阈值需要動態的數據,這個值用於這些動態數據的阈值
     */
    private final float initialValue = (float) 1.3;
    /**
     * 上一點的狀態,上升還是下降
     */
    private boolean lastStatus = false;
    /**
     * 是否上升的標志位
     */
    private boolean isDirectionUp = false;
    /**
     * 持續上升次數
     */
    private int continueUpCount = 0;
    /**
     * 上一點的持續上升的次數,為了記錄波峰的上升次數
     */
    private int continueUpFormerCount = 0;
    public boolean is_Acc=false;
    //  private int ACC=30;//手機感應器波動范圍,30以內判定手機處於靜止
    private int tempCount = 0;
    private final int valueNum = 4;
    /**
     * 用於存放計算阈值的波峰波谷差值
     */
    private float[] tempValue = new float[valueNum];
    /**
     * 記錄波峰數量
     */
    private int CountValue = 0;
    /**
     * 判斷傳感器是否在運行
     */
    public boolean IsRun=false; 

    public Acc(){
        //      LastUpdateTime=System.currentTimeMillis();
    }
    @Override
    public void onAccuracyChanged(int arg0, int arg1) {
        // TODO Auto-generated method stub

    }
    /**
     * 感應器狀態改變時自動調用此方法
     */
    @Override
    public void onSensorChanged(int arg0, float[] arg1) {
        // TODO Auto-generated method stub
        IsRun=true;
        if(arg0==Sensor.TYPE_ACCELEROMETER){
            //          JIUjia(arg1);
            gravityNew = (float) Math.sqrt(arg1[0] * arg1[0]
                    + arg1[1] * arg1[1] + arg1[2] * arg1[2]);
            DetectorNewStep(gravityNew);
        }
    }

    //   protected boolean JIUjia(float[] values) {
    //          if(F_Acc_x!=0){
    //              long currentUpdateTime = System.currentTimeMillis();   
    //              long timeInterval = currentUpdateTime - LastUpdateTime;    
    //              if(timeInterval < UPTATE_INTERVAL_TIME)
    //                  return false;
    //              LastUpdateTime=currentUpdateTime;
    //              float tem0=values[0]-F_Acc_x;
    //              float tem1=values[1]-F_Acc_y;
    //              float tem2=values[2]-F_Acc_z;
    //              System.out.println(Math.abs(tem0)+","+Math.abs(tem1)+","+Math.abs(tem2));
    //              if(Math.abs(tem0)>ACC||Math.abs(tem1)>ACC||Math.abs(tem2)>ACC)
    //                  is_Acc=true;
    //              
    //          }
    //          F_Acc_x=values[0];
    //          F_Acc_y=values[1];
    //          F_Acc_z=values[2];
    //          return is_Acc;
    //
    //      }

    /*
     * 檢測步子
     * 1.傳入sersor中的數據
     * 2.如果檢測到了波峰,並且符合時間差以及阈值的條件,則判定為1步
     * 3.符合時間差條件,波峰波谷差值大於initialValue,則將該差值納入阈值的計算中
     * */
    public void DetectorNewStep(float values) {
        if (gravityOld == 0) {
            gravityOld = values;
        } else {
            if (DetectorPeak(values, gravityOld)) {
                timeOfLastPeak = timeOfThisPeak;
                timeOfNow = System.currentTimeMillis();
                if ((timeOfNow - timeOfLastPeak) >= 250&& (peakOfWave - valleyOfWave >= ThreadValue)) {
                    timeOfThisPeak = timeOfNow;
                    //兩步之間間隔大於4秒則不算
                    if((timeOfNow-timeOfLastPeak)>40000)
                        CountValue=0;
                    else
                        CountValue++;
                    //只有手機連續搖晃4下或者以上才判定為走路
                    if(CountValue>=4)
                        is_Acc=true;
                    //                      mStepListeners.onStep();
                }
                if (timeOfNow - timeOfLastPeak >= 250&& (peakOfWave - valleyOfWave >= initialValue)) {
                    timeOfThisPeak = timeOfNow;
                    ThreadValue = Peak_Valley_Thread(peakOfWave - valleyOfWave);
                }
            }
        }
        gravityOld = values;
    }

    /*
     * 檢測波峰
     * 以下四個條件判斷為波峰:
     * 1.目前點為下降的趨勢:isDirectionUp為false
     * 2.之前的點為上升的趨勢:lastStatus為true
     * 3.到波峰為止,持續上升大於等於4次
     * 4.波峰值大於20
     * 記錄波谷值
     * 1.觀察波形圖,可以發現在出現步子的地方,波谷的下一個就是波峰,有比較明顯的特征以及差值
     * 2.所以要記錄每次的波谷值,為了和下次的波峰做對比
     * */
    public boolean DetectorPeak(float newValue, float oldValue) {
        lastStatus = isDirectionUp;
        if (newValue >= oldValue) {
            isDirectionUp = true;
            continueUpCount++;
        } else {
            continueUpFormerCount = continueUpCount;
            continueUpCount = 0;
            isDirectionUp = false;
        }

        if (!isDirectionUp && lastStatus&& (continueUpFormerCount >= 4 || oldValue >= 20&&oldValue<=40)) {
            peakOfWave = oldValue;
            return true;
        } else if (!lastStatus && isDirectionUp) {
            valleyOfWave = oldValue;
            return false;
        } else {
            return false;
        }
    }

    /*
     * 阈值的計算
     * 1.通過波峰波谷的差值計算阈值
     * 2.記錄4個值,存入tempValue[]數組中
     * 3.在將數組傳入函數averageValue中計算阈值
     * */
    public float Peak_Valley_Thread(float value) {
        float tempThread = ThreadValue;
        if (tempCount < valueNum) {
            tempValue[tempCount] = value;
            tempCount++;
        } else {
            tempThread = averageValue(tempValue, valueNum);
            for (int i = 1; i < valueNum; i++) {
                tempValue[i - 1] = tempValue[i];
            }
            tempValue[valueNum - 1] = value;
        }
        return tempThread;

    }

    /*
     * 梯度化阈值
     * 1.計算數組的均值
     * 2.通過均值將阈值梯度化在一個范圍裡
     * */
    public float averageValue(float value[], int n) {
        float ave = 0;
        for (int i = 0; i < n; i++) {
            ave += value[i];
        }
        ave = ave / valueNum;
        if (ave >= 8)
            ave = (float) 4.3;
        else if (ave >= 7 && ave < 8)
            ave = (float) 3.3;
        else if (ave >= 4 && ave < 7)
            ave = (float) 2.3;
        else if (ave >= 3 && ave < 4)
            ave = (float) 2.0;
        else {
            ave = (float) 1.3;
        }
        return ave;
    }
}

至此就全部結束了,各位如有其他問題可直接留言給我。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved