机器人使用估算的信标本地化
#python #本地化 #robotics #beacons

最近,我正在玩Estimote信标。信标被广泛用于在购物中心,博物馆和有意义的地方进行广告,并向附近的人们发送高度上下文,超本地的信息。这要归功于安装在设备上的蓝牙低能(ble)。电量寿命更长的功耗要少得多,这意味着这样的信标可以持续3年的单个电池电池。

对于提出的代码,您需要以下python软件包:

  • pybluez用于蓝牙功能,
  • beacontools管理信标,
  • pandas用于存储我们的数据。

此代码在Ubuntu上运行,我不确定它如何在其他操作系统上工作(由于蓝牙驱动程序)。您可能需要在此处查看有关要求的pyBluez文档:https://pybluez.github.io/

连接到信标

我们的第一步是导入二手软件包。我们将以清晰的方式导入pandas来存储我们的信标信息,以及beacontools软件包中的几件事。我们将使用扫描仪和特定的估算遥测框架和过滤器。

import pandas as pd
from beacontools import (
    BeaconScanner,
    EstimoteTelemetryFrameA,
    EstimoteTelemetryFrameB,
    EstimoteFilter,
)

为了使事情变得更容易,我创建了EstimoteScanner类,该类将管理beacontools方法,并以方便的方式存储信息。每当您看到self关键字时,您都可以扣除它来自该类别的。类的初始化是在__init__函数中完成的,没有任何其他参数 - 它从CSV文件中读取信标Metainfo,创建estectote滤波器并创建BeaconScanner

要读取信息,我们将使用pandasread_csv函数,如下面的代码所示。请注意,我将index_col设置为"identifier",将信标ID用作我们的数据框架ID。此外,我创建了两个新列,可以容纳rssi(信号强度)和distance(计算到信标)变量。

# Create DataFrame to store beacon info
self.devices = pd.read_csv("beacons.csv", index_col="identifier")
self.devices["rssi"] = 0
self.devices["distance"] = None

当我们打印出devices dataframe时,我们将获得以下输出:

                    name  x_pos  y_pos  rssi distance
identifier                                           
a7bfafb716c4a815   vader      0      2     0     None
c20770c80bd9f59c  tarkin     10      0     0     None
ec6247cf5570b993    leia     10     10     0     None

现在我们已经处理了数据存储,我们可以继续使用信标。首先,我们需要创建软件应寻找的信标列表。通过将信标的标识符作为参数传递给EstimoteFilter构造函数来处理这一点。我们将使用iterrows()函数通过我们的数据框,并为每个信标添加过滤器中的device_filters变量。

# Create scanning filters
self.device_filters = []
for index, _ in self.devices.iterrows():
    self.device_filters.append(
        EstimoteFilter(identifier=index)
    )

完成后,我们可以通过传递选定的遥测帧和我们的过滤器来创建扫描仪。

# Create the scanner
self.scanner = BeaconScanner(self._callback,
    packet_filter=[
        EstimoteTelemetryFrameA,
        EstimoteTelemetryFrameB
    ],
    device_filter=self.device_filters,
)

但是等等!如您所见,BeaconScanner中引用了一个称为_callback的函数。每当收到培根信息时,我们应该实现一个可以更新我们的数据框的回调功能。我正在根据从信标获得的identifierrssidistance的列选择该行。我们将在calibartion中使用该变量。

def _callback(self, bt_addr, rssi, packet, info):
    self.devices.loc[info["identifier"], "rssi"] = rssi
    self.devices.loc[
        info["identifier"], "distance"
    ] = self._calc_dist(rssi)

使用_calc_dist()函数计算distance。它使用标准距离计算公式。有趣的是MEASURED_POWER变量 - 这是信标应在4dBm处具有1米的力量。

请注意,如果您更改了估算信标的广播能力,则必须更新MEASURED_POWER变量以获得良好的距离校准。检查more info的估算论坛。

# Calibration power at 1 meter for 4dBm for Estimote Beacons
MEASURED_POWER = -66

def _calc_dist(self, rssi):
    return pow(10, (MEASURED_POWER - rssi) / 20)

现在要开始扫描,您只需要运行self.scanner.start()self.scanner.stop()收集数据时(通常在机器人达到目标时)。

机器人本地化

尽管使用信标的机器人本地化并不是最精确的方法,但使用此类系统具有一些优势。这可能是改善看起来相同的房间中机器人定位的工具(例如走廊)。信标的主要问题是,用于计算距离的信号功率可能会根据金属物体的数量,电子设备甚至建筑物结构而高度波动。

尽管如此,我们可以根据读数使用从扫描仪收集的数据来计算机器人的位置。我们将使用一种称为三征服的技术,该技术用于计算。地震中心。具有信标的静态点以及它们的距离,我们可以使用此技术来计算机器人位置。

该函数的输入参数是元组(x,y)表示的信标的位置的a,b,c,以及从我们的dataframe -da, db, dc中收集的米的距离。下面的代码仅将这些变量输入到三材的数学方程中,因此请随时复制一个。

三材代码可能有点草率,但是如果您有兴趣,请查看this scientific paper以查看计算如何推出。

def trilateration(a, b, c, da, db, dc):
    """Function responsible for Trilateration
    Parameters
    ----------
    a, b, c: tuple
        Contains the position of the beacon (x, y)
    da, db, dc: float
        The distance to the beacon in meters.
    """
    if da is None or db is None or dc is None:
        return None

    W = (
        pow(da, 2)
        - pow(db, 2)
        - pow(a[0], 2)
        - pow(a[1], 2)
        + pow(b[0], 2)
        + pow(b[1], 2)
    )
    Z = (
        pow(db, 2)
        - pow(dc, 2)
        - pow(b[0], 2)
        - pow(b[1], 2)
        + pow(c[0], 2)
        + pow(c[1], 2)
    )

    x = (W * (c[1] - b[1]) - Z * (b[1] - a[1])) / (
        2
        * (
            (b[0] - a[0]) * (c[1] - b[1])
            - (c[0] - b[0]) * (b[1] - a[1])
        )
    )
    y = (W - 2 * x * (b[0] - a[0])) / (2 * (b[1] - a[1]))
    y2 = (Z - 2 * x * (c[0] - b[0])) / (2 * (c[1] - b[1]))
    y = (y + y2) / 2

    return x, y

概括

使用BLE信标进行机器人本地化是一个有趣的项目。与其他技术相比,您获得的结果并不是非常精确的,但是可以在周围的环境中快速概述。该方法可以大大增强您的其他算法,尤其是在周围有许多信标(想想购物中心)时。该代码可以轻松地传输到任何Ubuntu运行设备,因此可以与ROS一起使用。