百度地图绘制实时路线以及最短线路规划

如何使用百度地图绘制实时路线以及最短线路规划

最近在做百度地图的实时路线绘制,发现一些问题,比如由于定位漂移带来的路线绘制偏差,还有由于定位漂移,导致人未走动时,也会绘制路线等。百度鹰眼的线路纠偏个人感觉很一般啊。而且有限漂移了两百米的点他也没有纠正过来。所以最后还是决定自己写一个纠偏吧。而且百度地图官方的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<LatLng> pointList = new ArrayList<LatLng>();
    /**
//   * 判断是否处于暂停
//   */
    //  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(constant<pointList.size()){
                        if(DistanceUtil.getDistance(pointList.get(constant),ll)>DistanceUtil.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;i<WalkingRoute.getRouteLines().get(0).getAllStep().size();i++){
                        pointList.addAll(WalkingRoute.getRouteLines().get(0).getAllStep().get(i).getWayPoints());
                    }
                    save("时间: "+getStringDate()+" 总点数: "+pointList.size());
                }
                else
//                  Toast.makeText(MainActivity.this, "获取线路失败", 3000).show();
                    System.out.println("ccccccccccccccccccc");
            }

        };
        mSearch.setOnGetRoutePlanResultListener(listener);
        //长按地图监听
        BaiDuMap.setOnMapLongClickListener(new OnMapLongClickListener() {

            @Override
            public void onMapLongClick(LatLng arg0) {
                // TODO Auto-generated method stub
                EndLL=arg0;
                StartRoutePlan();
            }
        });
//      mSearch.destroy();
        Toast.makeText(this, "正在定位....", 3000).show();
    }
    /**
     * 初始化资源
     */
    protected void init(){
        map_v=(MapView)findViewById(R.id.bmapView);
        bitmap = BitmapDescriptorFactory.fromResource(R.drawable.map_d);
        StartBitmap= BitmapDescriptorFactory.fromResource(R.drawable.start_bitmap);
        EndBitmap= BitmapDescriptorFactory.fromResource(R.drawable.end_bitmap);
        //      locationManager = (LocationManager) getSystemService(this.LOCATION_SERVICE);
        BaiDuMap=map_v.getMap();
        locationClient = new LocationClient(this);
        LocationClientOption option = new LocationClientOption();
        option.setOpenGps(true);        //是否打开GPS
        option.setCoorType("bd09ll");       //设置返回值的坐标类型。bd09ll百度加密经纬度坐标,bd09百度加密墨卡托坐标,gcj02国测局加密经纬度坐标
        option.setPriority(LocationClientOption.GpsOnly);  //设置定位优先级,只取gps定位;
        option.setProdName(APP_FOLDER_NAME); //设置产品线名称。
        option.setScanSpan(time);    //设置定时定位的时间间隔。单位毫秒
        locationClient.setLocOption(option);
        BaiDuMap.setMapType(BaiduMap.MAP_TYPE_NORMAL);//普通地图模式 ;MAP_TYPE_SATELLITE为卫星地图;MAP_TYPE_NONE空白地图;
        BaiDuMap.setTrafficEnabled(false);//不开启交通视图;
        map_v.showZoomControls(false);//不开启底部放大缩小 图标;
        BaiDuMap.animateMapStatus(MapStatusUpdateFactory.zoomTo(18));//设置地图缩放
        BaiDuMap.setMyLocationEnabled(true);//开启定位图层
        BaiDuMap.setMaxAndMinZoomLevel(18.0f,1.0f);
        mSearch = RoutePlanSearch.newInstance();
        progressDialog=new ProgressDialog(this);
    }

    @Override
    protected void onStart() {
        // TODO Auto-generated method stub
        super.onStart();
    }
    @Override
    protected void onDestroy() {
        // TODO Auto-generated method stub
        super.onDestroy();
        map_v.onDestroy();
        BaiDuMap.setMyLocationEnabled(false);
        locationClient.stop();
        map_v = null;
        releaseWakeLock();
        sm.unregisterListener(acc);
        mSearch.destroy();
        saveArray();
    }

    @Override
    protected void onPause() {
        // TODO Auto-generated method stub
        super.onPause();
        map_v.onPause();
    }
    @Override
    public boolean onMenuItemSelected(int featureId, MenuItem item) {
        // TODO Auto-generated method stub
        if(item.getItemId()==R.id.action_settings)
        {
            progressDialog.setTitle("路线规划");
            progressDialog.setMessage("正在清除路线请稍后。。");
            progressDialog.show();
            isGetRoute=false;
            if(pointList!=null||pointList.size()>0)
                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_" + i);
            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
    //   */
    //  protected void loadArray(Context mContext) {
    //      SharedPreferences mSharedPreference1=getSharedPreferences("lat", Context.MODE_PRIVATE);
    //      //        pointList.clear();
    //      int size = mSharedPreference1.getInt("Status_size", 0);
    //
    //      for(int i=0;i<size;i++) {
    //          Double lat1=Double.valueOf(mSharedPreference1.getString("lat_"+i, null));
    //          Double lon1=Double.valueOf(mSharedPreference1.getString("lat_"+i, null));
    //          pointList.add(new LatLng(lat1, lon1));
    //      }
    //  }
    /*
     * 删除xml文件
     */
    private void deleteXML() {
        File file = new File("/data/data/" + getPackageName().toString()
                + "/shared_prefs", "lat.xml");
        if (file.exists()) {
            file.delete();
        }
    }
    /*
     * 显示实时轨迹
     *
     * @param realtimeTrack
     */
    protected void showRealtimeTrack(BDLocation location) {
        double latitude = location.getLatitude();
        double longitude = location.getLongitude();
        if (Math.abs(latitude - 0.0) < 0.000001 && Math.abs(longitude - 0.0) < 0.000001) {
            Toast.makeText(this, "当前无轨迹点", 3000).show();
        } else {
            latLng = new LatLng(latitude, longitude);
            if (IsMove(latLng,location)) {
                // 绘制实时点
                drawRealtimePoint(latLng);
            }
        }

    }

    /*
     * 绘制实时点
     *
     * @param points
     */
    private void drawRealtimePoint(LatLng point) {

        BaiDuMap.clear();
        polyline=null;
        MapStatus mMapStatus = new MapStatus.Builder().target(point).build();

        msUpdate = MapStatusUpdateFactory.newMapStatus(mMapStatus);

        overlay = new MarkerOptions().position(point)
                .icon(bitmap).zIndex(9).draggable(true);

        if (pointList.size() >=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;
    }
}

至此就全部结束了,各位如有其他问题可直接留言给我。

时间: 2024-10-21 13:29:26

百度地图绘制实时路线以及最短线路规划的相关文章

2016计蒜之道复赛A 百度地图的实时路况

百度地图的实时路况功能相当强大,能方便出行的人们避开拥堵路段.一个地区的交通便捷程度就决定了该地区的拥堵情况.假设一个地区有 nnn 个观测点,编号从 111 到 nnn.定义 d(u,v,w)d(u,v,w)d(u,v,w) 为从 uuu 号点出发,严格不经过 vvv 号点,最终到达 www 号点的最短路径长度,如果不存在这样的路径,d(u,v,w)d(u,v,w)d(u,v,w) 的值为 −1-1−1. 那么这个地区的交通便捷程度 PPP 为: P=∑1≤x,y,z≤n,x≠y,y≠zd(x

百度地图的实时路况

百度地图的实时路况功能相当强大,能方便出行的人们避开拥堵路段.一个地区的交通便捷程度就决定了该地区的拥堵情况.假设一个地区有 nn 个观测点,编号从 11 到 nn.定义 d(u,v,w)d(u,v,w) 为从 uu 号点出发,严格不经过 vv 号点,最终到达 ww 号点的最短路径长度,如果不存在这样的路径,d(u,v,w)d(u,v,w) 的值为 -1−1. 那么这个地区的交通便捷程度 PP 为: P = \sum_{1 \leq x,y,z \leq n , x \neq y , y \ne

北京地铁最短线路规划

一.项目需求 设计一个能进行北京地铁最短线路规划的程序. 二.文件存储 用一个名为data.txt的文件来存储所有北京地铁线路及站点信息,如下所示. 三.算法代码 本次项目的设计用到的语言是java语言,主要的规划最短路径的算法采用dijkstra算法 public class PathControl { private static List<Station> analysisList = new ArrayList<>(); private static HashMap<

Python调用百度地图API(路线规划、POI检索)——第一部分

项目的目的是为了查询某个点附近某些POI的最近距离,例如查询天安门到附近最近的商场的距离(时间) 1.百度地图API 程序中用到百度地图的两个API,分别是 (1)路线规划服务(又名Direction API):http://lbsyun.baidu.com/index.php?title=webapi/direction-api-v2 (2)地点检索服务(又名Place API):http://lbsyun.baidu.com/index.php?title=webapi/guide/webs

2016计蒜之道复赛 百度地图的实时路况 floyd+cdq分治

链接:https://nanti.jisuanke.com/t/11217 奉上官方题解: 枚举 d(x , y , z) 中的 y,把 y 从这个图中删去,再求这时的全源最短路即可,使用 Floyd 算法来做上述过程. Floyd 算法可以是一个增量的过程,虽然第一维一般都是从 1枚举到 k但是这个枚举的顺序并不影响最后的结果. 所以如果可以预处理出对于每个点 y,只剩 y 没有在 Floyd 的第一维枚举到的矩阵,这个矩阵的值就是不经过 y 点的全源最短路. 所以使用分治,每一次把点集拆成两

[计蒜客]百度地图的实时路况

description 给出有向图的点数\(n\)和邻接矩阵\(G\), 求\[P=∑_{1≤x,y,z≤n,x≠y,y≠z}d(x,y,z)\] 其中\(d(x,y,z)\)表示从\(x\)不经过\(y\)到\(z\)的最短路,如果无法到达则为\(-1\) data range \[4≤n≤300,?1≤G_{i,j}≤10000,G_{i,i}=0\] solution 首先你要知道\(floyed\)的本质是枚举中转点. 那么不经过\(y\)点的最短路矩阵相当于使用除\(y\)以外的点作为

2016计蒜之道复赛 百度地图的实时路况 分治+Floyd

题目链接:https://nanti.jisuanke.com/t/A1108 这道题还挺有意思的.让我对Floyd的了解又加深了一点. 首先我们重新审视Floyd这三重循环到底有什么用?第一层是枚举中间结点,第二三层是枚举路径起点和终点.那么是不是当第一层循环还没枚举到的点,此时的最短路就不会经过这这些点呢? 答案是肯定的.所以这道题也就可以做了. 题目是要求我们计算  第一层循环缺一个点的情况下  的所有最短路之和.我们当然可以枚举这个缺的点,那么时间复杂度是O(n^4).不能接受. 那么我

百度地图的实时路况 2016 计蒜之道 复赛

https://nanti.jisuanke.com/t/A1108 way1: 应该很多同学的做法都是对于每次y,每次x,dijkstra+堆优化 n^2 * nlogn 其实log(300)很小... way2: 题解方法真心优秀!!! cdq分治 有助于理解floyd:每次加入一个可以使用的点,加n次,顺序可以调整 本题:对于每个y,仅仅是y点不能使用 每次计算1/2,cdq剩下的1/2(left,right分别来一次),直到只剩下一个数,这个点不用于求最短路.所有点都有且仅有一次出现“只

android socket 百度地图 实时定位

Socket服务 首先开启一个启动Socket的服务 publicclassSocketNetService extends Service{ privatefinal String TAG = "SocketNetService"; publicstatic Thread NetThread; publicstatic Socket socket; private InetAddress address; publicstaticbooleanisFristConn = true;