蓝牙定位算法——处理多径效应问题

蓝牙定位算法——处理多径效应问题

最近在做蓝牙定位项目的时候,标签总会在很短的时间窗口内上传多个数据基本相同的报文。

这里的Beacon-Tag-Base之间的数据传递逻辑是:

RSSI
RSSI
RSSI
RSSI
Beacon:RSSI pairs
Beacon1
Tag
Beacon2
Beacon3
Beaconx
BLE_Base

Tag在固定时间窗口内收集齐3个以上Beacon的广播信息后,进行一次广播,系统根据Tag的广播数据进行Tag定位。

当短时间内出现多条来自Tag且数据相同的报文时,基本可以判定为多径效应造成的数据重复接收。BLE基站没有对多径效应进行处理,这就需要服务器端的我来解决了。

想要解决这个问题其实也很简单,利用一个字典来保存当前收到报文的tag_code、时间戳以及rssi,收到新数据时,检查字典是否包含该tag_code,包含就对比时间戳,如果两者比较接近(比如相差不到0.2秒),则直接舍弃掉。舍弃掉的原因很简单:

  • 就报文而言,除了时间和Tag自身的RSSI外是没有区别的,计算出来的定位点也是同一个点,所以没必要
  • 实际的业务场景中对于定位频率的要求很低,可能10秒一定位,在满足基本业务需求的情况下还得照顾电池续航能力,所以其实1秒时间窗口内的报文都可以丢弃,只有在给客户展示的时候需要适当加快定位频率

python代码的实现 be like


......

TIME_WINDOW = 0.25  # 秒
<= RSSI_DIFF_TOLERANCE = 6
recent_beacons = {}
class BeaconData:
    def __init__(self, major, minor, rssi):
        self.major = major
        self.minor = minor
        self.rssi = rssi

    def __str__(self):
        return f"{self.minor[-1:]}:{self.rssi}"

def extractTagAndBeacon(data):

    ......
    
    tag_id = ''.join(f'{byte:02X}' for byte in data[19:21])
    base_code = ''.join(f'{byte:02X}' for byte in data[4:6])

    current_time = datetime.now().strftime('%H:%M:%S.%f')[:-3]
    current_timestamp = time.time()
    rssi = data[6] - 256

    if tag_id in recent_beacons:
        last_timestamp, last_rssi = recent_beacons[tag_id]
        if current_timestamp - last_timestamp < TIME_WINDOW and abs(last_rssi - rssi) <= RSSI_DIFF_TOLERANCE:
            #print(f"Discarding multipath effect data for tag: {tag_id}")
            recent_beacons[tag_id] = (current_timestamp, rssi)
            return None, None, None
    recent_beacons[tag_id] = (current_timestamp, rssi)
    
    ......
    
    # survive from 多径效应检测,开始处理报文数据
    return tag_id, iBeacon_count, beacon_data_list

def receiveData():
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    sock.bind(('0.0.0.0', 8081))
    print("Listening on port 8081...")

    while True:
        data, _ = sock.recvfrom(1024)
        while len(data) >= 45:
            tag_code, iBeacon_count, beacon_data_list = extractTagAndBeacon(data)
            if not tag_code or not iBeacon_count or not beacon_data_list or iBeacon_count < 3:
                break
                
            # 处理业务
            ......
            
rec_thread = threading.Thread(target=receiveData, daemon=True)
rec_thread.start()
  • 10
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值