蓝牙RSSI定位入门到精通(1)---三点定位

下一篇:蓝牙RSSI定位入门到精通(2)–指纹法

点击:室内定位主页目录+一维实战+二维实战+安卓惯性导航基础

蓝牙5.0的发布,降低了功耗,大大提高了定位的准确度和距离,而它的定位–物联网设备又使室内定位更加火热。BLE功能强大,通过它不用连接的特性,可以实现多种功能,可以想象:旅游时走到景点旁,手机自动推送景点介绍;上学时,通过穿戴物联网设备查看是否出勤。本篇主要介绍,通过手机设备模拟信标实现室内实时导航和人员实时定位。

  • 实现原理
    由于是手机模拟信标,所以使用传统蓝牙,通过无需连接的特性发送广播获得信标的rssi通过距离算法获得与信标的距离,通过三个信标的距离与坐标用三点定位算法得到手机位置。
    一,安卓蓝牙模块的使用

1,安卓使用蓝牙模块需要添加权限,在AndroidManifest.xml添加如下代码

 <uses-permission android:name="android.permission.BLUETOOTH"/>
 <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
 <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
 <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

2,安卓6.0之后,使用蓝牙需要申请权限。所以需要加入如下代码

         ActivityCompat.requestPermissions(this,new String[]
        {Manifest.permission.ACCESS_FINE_LOCATION},MY_PERISSION);//获得权限

3,现在可以初始化蓝牙,创建蓝牙适配对象和打开蓝牙

     private void init_ble() {
         mBluetoothAdapter= BluetoothAdapter.getDefaultAdapter();

        if (!mBluetoothAdapter.isEnabled()){
              mBluetoothAdapter.enable();
        }
    }

二,蓝牙注册和广播

1,蓝牙广播

//注册广播搜索蓝牙
    private void registerReceiver() {
        IntentFilter filter = new IntentFilter();//筛选广播
        filter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
        filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
        filter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);
        filter.addAction(BluetoothDevice.ACTION_FOUND);
        filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
        registerReceiver(mBluetoothReceiver, filter);//注册
    }

2,蓝牙广播和停止广播

    public void start(View view) {
        mBluetoothAdapter.startDiscovery();
        Textview1.setText("开始搜索");

    }
public void end(View view) {
        if(mBluetoothAdapter.isDiscovering())//蓝牙是否在扫描过称中
        mBluetoothAdapter.cancelDiscovery();
        Textview1.setText("停止广播");
    }

3,蓝牙开始广播会创建线程,进行广播的回调。重写onReceive获得RSSI,在回调中尽量将处理放入线程中

    //蓝牙广播接受者
    private BroadcastReceiver mBluetoothReceiver = new BroadcastReceiver(){
        @Override
        public void onReceive(Context context, Intent intent) {

            String action = intent.getAction();
            Textview1.append("\n-------------------------------");
            Textview1.append("\n获得广播:"+action);
         if(BluetoothDevice.ACTION_FOUND.equals(action))//发现广播
         {

        new Thread()
        {
            @Override
            public void run() {
                super.run();

                try {
                BluetoothDevice scanDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                   if (scanDevice.getBondState() != BluetoothDevice.BOND_BONDED) //如果没有绑定short rssi = intent.getShortExtra(BluetoothDevice.EXTRA_RSSI, Short.MIN_VALUE);
                               Textview1.append("\n     信标:" + scanDevice.getName() );
                               Textview1.append("\n     address: "+scanDevice.getAddress());
                               Textview1.append("\n     rssi:" + rssi);
                               //获得RSSI} catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }.start();

补充,用ble蓝牙

BLE蓝牙使用BluetoothLeScanner来进行扫描

  BluetoothLeScanner scanner=mBluetoothAdapter.getBluetoothLeScanner();
  
  scanner.startScan(mScanCallback);
  
  private ScanCallback mScanCallback = new ScanCallback() {
       @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
       @Override
     //  public  void onScanResult( BluetoothAdapter device,int rssi,byte[]scan_record)
     //  {
     //      Textview1.append(String.valueOf(rssi));
      // }
       public void onScanResult(int callbackType, final ScanResult result) {
             runOnUiThread(new Runnable() {
                   @Override
                   public void run() {
                      final iBeacon ibeacon = iBeaconClass.fromScanData(result.getDevice(),result.getRssi(),result.getScanRecord().getBytes());
                       Textview1.append( "\n蓝牙名称"+ibeacon.name);
                       Textview1.append("\n" +"蓝牙地址"+ibeacon.bluetoothAddress);
                       Textview1.append( "\n" +"uuid"+ibeacon.proximityUuid);
                       Textview1.append( "\n" +"major"+ibeacon.major);
                       Textview1.append( "\n" +"minor"+ibeacon.minor);
                       Textview1.append( "\n" +"rssi"+ibeacon.rssi);
                       Textview1.append( "\n" +"distance"+ibeacon.distance);
                       Textview1.append( "\n" +"power"+ibeacon.txPower);
                   }
               });
            }



   };

三,距离算法和三点定位算法

1,三点定位算法是最简单的测距方法,距离算法基于无线电衰减模型,rssi与距离的对数正比。即可得到公式
d = 10^((abs(RSSI) - A) / (10 * n))
d - 计算所得距离
RSSI - 接收信号强度(负值)
A - 发射端和接收端相隔1米时的信号强度
n - 环境衰减因子

          double Rssi = Math.abs(rssi);
                               double power = (Rssi - 60) / (10.0 * 3.3);
                               //93=10米    60=1米
                               String location=String.valueOf(Math.pow(10, power));
                               Textview1.append("\n     距离为:"+location.substring(0,6)+"米");

2,三点定位算法,在基于无线电衰减模型中能获得固定的一个点坐标。
已知三个信标的坐标,已经通过三个信标的RSSI得到与信标的距离。即可得到定位的坐标。
三点定位

if (size>=3)//三点定位
                    {
                        double p0_x=Double.parseDouble(Arr_coord.get(0).substring(0,Arr_coord.get(0).indexOf("*")));//截取获得信标的坐标
                        double p0_y=Double.parseDouble(Arr_coord.get(0).substring(Arr_coord.get(0).indexOf("*")+1));
                        double p1_x=Double.parseDouble(Arr_coord.get(1).substring(0,Arr_coord.get(1).indexOf("*")));
                        double p1_y=Double.parseDouble(Arr_coord.get(1).substring(Arr_coord.get(1).indexOf("*")+1));
                        double p2_x=Double.parseDouble(Arr_coord.get(2).substring(0,Arr_coord.get(2).indexOf("*")));
                        double p2_y=Double.parseDouble(Arr_coord.get(2).substring(Arr_coord.get(2).indexOf("*")+1));
                        double a=p0_x-p2_x;
                        double b=p0_y-p2_y;
                        double c= Math.pow(p0_x, 2) - Math.pow(p2_x, 2) + Math.pow(p0_y, 2) - Math.pow(p2_y, 2) + Math.pow(Double.parseDouble(Arr_loc.get(2)), 2) - Math.pow(Double.parseDouble(Arr_loc.get(0)), 2);
                        double d=p1_x-p2_x;
                        double e=p1_y-p2_y;
                        double f=Math.pow(p1_x, 2) - Math.pow(p2_x, 2) + Math.pow(p1_y, 2) - Math.pow(p2_y, 2) + Math.pow(Double.parseDouble(Arr_loc.get(2)), 2) - Math.pow(Double.parseDouble(Arr_loc.get(1)), 2);
                        double x=(b*f-e*c)/(2*b*d-2*a*e);
                        double y=(a*f-d*c)/(2*a*e-2*b*d);
                        String string=String.valueOf(x).substring(0,5)+","+String.valueOf(y).substring(0,5);
                        Textview1.append("\n*************************\n你的坐标为:"+string+"\n*************************");
//Arr_loc存放某个信标的距离
//Arr_coord存放某个信标的x*y坐标
                    }

四,结果和总结

1,获得的坐标有较大的偏移。在现实生活中,由于环境的不同,甚至在空旷地带也无法实现无线电衰减模型。有时还会发生超过10dbm的偏移。如下,为我购买的三个不同的信标测试图。
上面是RSSI的方差,下面是RSSI的强度。在一米内比较准确,一米后,就很难确定位置了。
(甚至有些差的信标,在1米的波动都很大,如绿色线)
这里写图片描述

2,附上效果图

在这里插入图片描述


  • 31
    点赞
  • 216
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 80
    评论
### 回答1: 蓝牙(RSSI)室内定位是一种基于蓝牙信号强度(RSSI)和距离的室内定位技术,可以在室内环境中实现精确的位置跟踪服务。目前,Android平台提供了许多用于蓝牙定位的API和工具,开发人员可以使用这些工具来实现室内定位功能。 在实现蓝牙(RSSI)室内定位之前,需要先进行站点调查和信号质量测试。站点调查可以用于确定信标放置的位置、数量和信号范围等因素。信号质量测试可以确定信标的信号强度和覆盖范围,以便更好的设计和优化蓝牙定位系统。 在Android平台中,可以使用BluetoothAdapter API来扫描周围的蓝牙设备,获取设备的RSSI值和MAC地址等信息。一旦获取了RSSI值,就可以通过算法计算出设备与信标之间的距离和位置信息,并将其显示在用户界面上。具体的算法可以使用基于信号强度指数的方法,例如Path Loss和Trilateration的方法来进行定位计算。 需要注意的是,蓝牙(RSSI)室内定位技术也存在一些挑战和限制。例如,信号强度受环境因素的影响,如环境噪声和干扰等,这可能会导致定位精度不是特别高。此外,室内定位需要多个信标进行多点定位,成本也会相应增加。 总之,在Android开发中,使用蓝牙(RSSI)室内定位技术可以实现室内定位和位置跟踪功能,为商业和社会提供更多可能性。 ### 回答2: 在Android开发中,可以通过蓝牙RSSI(接收信号强度指数)数据实现室内定位RSSI是指接收到的信号强度,通过测量不同位置的RSSI值,就能够确定设备的位置。 首先需要获取设备的蓝牙信号强度值,这可以通过蓝牙扫描获取。然后建立一个基站位置数据库,将不同位置的蓝牙信号强度值记录下来。当需要定位时,就可以通过比对当前设备的蓝牙信号强度值和基站位置数据库中的信号强度值,来确定设备所处的位置。 室内定位的精度受到多种因素影响,比如墙体厚度、金属物体等会影响信号强度。因此在开发中需要进行精细的调试和优化。同时,蓝牙定位也有一些局限性,如需要用户开启蓝牙蓝牙信号强度值容易受到干扰等。 总之,蓝牙RSSI室内定位是一种比较成熟的技术,在Android开发中也有较多的应用场景,但仍需要开发者进行精细的调试和优化,来提高室内定位的精度和性能。 ### 回答3: 蓝牙RSSI室内定位,是指通过蓝牙信号强度指示(RSSI)来确定物体或设备在室内的具体位置。这种方法适用于室内定位、追踪和导航等场景,但是有其限制:比如,受到干扰等外部环境因素的影响,精准度往往难以达到预期。 对于Android开发来说,实现蓝牙RSSI室内定位需要使用蓝牙模块,并结合相关的定位算法,如三角定位法、指纹定位法等。一般步骤如下: 1.获取蓝牙设备的RSSI值。通过将扫描到的蓝牙设备进行连接,获取其信号强度值。 2.建立基站地图。在室内设定多个基站,获取它们的位置信息,并记录其强度值。 3.计算物体位置。结合已知的基站位置和它们的强度值,使用相关算法计算物体位置及其误差范围。 4.优化算法。如增加基站数量、调整基站位置等,提升室内定位精确度。 Android开发中,需要使用一些相关技术包和类库,如蓝牙适配器、手动操作权限等,较为复杂。值得注意的是,该技术需要有精确的物理地图、较多的基站数量以及较强的数据处理能力,因此在应用中的实际场景时需要谨慎考虑。
评论 80
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

工农村贴膜小哥

我倒是要看看是那个憨憨在给我打

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值