BLE(iBeacons)三边测量定位技术

18

我是德国福特万根大学的一名学生。

我正在撰写我的论文,对iBeacon和其背后的技术非常感兴趣。我的目前项目是将信标技术与GPS、无线定位、GSM和NFC等其他技术进行比较。为了我的论文,我将创建不同的用例并比较结果。

在过去的几天里,我试图确定我的房间中的位置。我使用三个信标的相对距离(精度)并为每个信标赋予房间中的固定位置。我得到三个圆并计算出6个交点。当弧度(精度)太低时,我人为地增加这个值。然后我看哪一个交点(6个交点之一)最近。(三个最近点)通过这些点,我得到一个三角形,并据此计算出中心点。

我的问题是结果并不是最好的。

我在这里找到了更好的解决方案:

https://gis.stackexchange.com/questions/40660/trilateration-algorithm-for-n-amount-of-points

但我在实现它在Objective C上遇到了麻烦。但我理解该解决方案。我如何在Objective C中导入或获取它。我找到了一些库(C,C ++),但我不太确定哪个库是最好的。

对我来说最好的解决方案将是一个可以计算这些点(x1、x2、x3,-,y1、y2、y3,-,r1、r2、r3)的Objective C数学库。

现在我的计算图形


你在这方面有什么运气吗? - Tom Irving
我也对第一个解决方案感兴趣,因为我想尝试一下开发一种旅游指南应用程序的可能性。对我来说准确度不是最重要的。您能分享逻辑或甚至一些计算代码吗? - Luuk D. Jansen
你介意分享一下你是如何实现你发布的那个iPad应用程序的吗?我已经根据维基百科的三边测量文章(http://en.m.wikipedia.org/wiki/Trilateration)设计出了一个算法,但我目前正在尝试找到在iOS中映射我的坐标的最佳方法。 - Yazid
1个回答

19
我曾经也面临同样的问题,后来找到了这个用 Python 写的解决方案。我尝试将代码转换成 Objective-C 并使用同样的测试数据,在结果准确性上没有问题。我修改了代码以便接受 2 维向量作为输入。

测试数据是:

P1 = (3,0) r1 = 6.4031
P2 = (9,0) r2 = 4.1231
P3 = (4,8) r3 = 5.6568

我将这些数据输入到代码中:

//P1,P2,P3 is the point and 2-dimension vector
NSMutableArray *P1 = [[NSMutableArray alloc] initWithCapacity:0];
[P1 addObject:[NSNumber numberWithDouble:3]];
[P1 addObject:[NSNumber numberWithDouble:0]];


NSMutableArray *P2 = [[NSMutableArray alloc] initWithCapacity:0];
[P2 addObject:[NSNumber numberWithDouble:9]];
[P2 addObject:[NSNumber numberWithDouble:0]];

NSMutableArray *P3 = [[NSMutableArray alloc] initWithCapacity:0];
[P3 addObject:[NSNumber numberWithDouble:4]];
[P3 addObject:[NSNumber numberWithDouble:8]];

//this is the distance between all the points and the unknown point
double DistA = 6.4031;
double DistB = 4.1231;
double DistC = 5.6568;

// ex = (P2 - P1)/(numpy.linalg.norm(P2 - P1))
NSMutableArray *ex = [[NSMutableArray alloc] initWithCapacity:0];
double temp = 0;
for (int i = 0; i < [P1 count]; i++) {
    double t1 = [[P2 objectAtIndex:i] doubleValue];
    double t2 = [[P1 objectAtIndex:i] doubleValue];
    double t = t1 - t2;
    temp += (t*t);
}
for (int i = 0; i < [P1 count]; i++) {
    double t1 = [[P2 objectAtIndex:i] doubleValue];
    double t2 = [[P1 objectAtIndex:i] doubleValue];
    double exx = (t1 - t2)/sqrt(temp);
    [ex addObject:[NSNumber numberWithDouble:exx]];
}

// i = dot(ex, P3 - P1)
NSMutableArray *p3p1 = [[NSMutableArray alloc] initWithCapacity:0];
for (int i = 0; i < [P3 count]; i++) {
    double t1 = [[P3 objectAtIndex:i] doubleValue];
    double t2 = [[P1 objectAtIndex:i] doubleValue];
    double t3 = t1 - t2;
    [p3p1 addObject:[NSNumber numberWithDouble:t3]];
}

double ival = 0;
for (int i = 0; i < [ex count]; i++) {
    double t1 = [[ex objectAtIndex:i] doubleValue];
    double t2 = [[p3p1 objectAtIndex:i] doubleValue];
    ival += (t1*t2);
}

// ey = (P3 - P1 - i*ex)/(numpy.linalg.norm(P3 - P1 - i*ex))
NSMutableArray *ey = [[NSMutableArray alloc] initWithCapacity:0];
double p3p1i = 0;
for (int  i = 0; i < [P3 count]; i++) {
    double t1 = [[P3 objectAtIndex:i] doubleValue];
    double t2 = [[P1 objectAtIndex:i] doubleValue];
    double t3 = [[ex objectAtIndex:i] doubleValue] * ival;
    double t = t1 - t2 -t3;
    p3p1i += (t*t);
}
for (int i = 0; i < [P3 count]; i++) {
    double t1 = [[P3 objectAtIndex:i] doubleValue];
    double t2 = [[P1 objectAtIndex:i] doubleValue];
    double t3 = [[ex objectAtIndex:i] doubleValue] * ival;
    double eyy = (t1 - t2 - t3)/sqrt(p3p1i);
    [ey addObject:[NSNumber numberWithDouble:eyy]];
}


// ez = numpy.cross(ex,ey)
// if 2-dimensional vector then ez = 0
NSMutableArray *ez = [[NSMutableArray alloc] initWithCapacity:0];
double ezx;
double ezy;
double ezz;
if ([P1 count] !=3){
    ezx = 0;
    ezy = 0;
    ezz = 0;

}else{
    ezx = ([[ex objectAtIndex:1] doubleValue]*[[ey objectAtIndex:2]doubleValue]) - ([[ex objectAtIndex:2]doubleValue]*[[ey objectAtIndex:1]doubleValue]);
    ezy = ([[ex objectAtIndex:2] doubleValue]*[[ey objectAtIndex:0]doubleValue]) - ([[ex objectAtIndex:0]doubleValue]*[[ey objectAtIndex:2]doubleValue]);
    ezz = ([[ex objectAtIndex:0] doubleValue]*[[ey objectAtIndex:1]doubleValue]) - ([[ex objectAtIndex:1]doubleValue]*[[ey objectAtIndex:0]doubleValue]);

}

[ez addObject:[NSNumber numberWithDouble:ezx]];
[ez addObject:[NSNumber numberWithDouble:ezy]];
[ez addObject:[NSNumber numberWithDouble:ezz]];


// d = numpy.linalg.norm(P2 - P1)
double d = sqrt(temp);

// j = dot(ey, P3 - P1)
double jval = 0;
for (int i = 0; i < [ey count]; i++) {
    double t1 = [[ey objectAtIndex:i] doubleValue];
    double t2 = [[p3p1 objectAtIndex:i] doubleValue];
    jval += (t1*t2);
}

// x = (pow(DistA,2) - pow(DistB,2) + pow(d,2))/(2*d)
double xval = (pow(DistA,2) - pow(DistB,2) + pow(d,2))/(2*d);

// y = ((pow(DistA,2) - pow(DistC,2) + pow(i,2) + pow(j,2))/(2*j)) - ((i/j)*x)
double yval = ((pow(DistA,2) - pow(DistC,2) + pow(ival,2) + pow(jval,2))/(2*jval)) - ((ival/jval)*xval);

// z = sqrt(pow(DistA,2) - pow(x,2) - pow(y,2))
// if 2-dimensional vector then z = 0
double zval;
if ([P1 count] !=3){
    zval = 0;
}else{
    zval = sqrt(pow(DistA,2) - pow(xval,2) - pow(yval,2));
}

// triPt = P1 + x*ex + y*ey + z*ez
NSMutableArray *triPt = [[NSMutableArray alloc] initWithCapacity:0];
for (int i = 0; i < [P1 count]; i++) {
    double t1 = [[P1 objectAtIndex:i] doubleValue];
    double t2 = [[ex objectAtIndex:i] doubleValue] * xval;
    double t3 = [[ey objectAtIndex:i] doubleValue] * yval;
    double t4 = [[ez objectAtIndex:i] doubleValue] * zval;
    double triptx = t1+t2+t3+t4;
    [triPt addObject:[NSNumber numberWithDouble:triptx]];
}

NSLog(@"ex %@",ex);
NSLog(@"i %f",ival);
NSLog(@"ey %@",ey);
NSLog(@"d %f",d);
NSLog(@"j %f",jval);
NSLog(@"x %f",xval);
NSLog(@"y %f",yval);
NSLog(@"y %f",yval);
NSLog(@"final result %@",triPt);

我使用上述的测试数据在笛卡尔图中绘制了图形,得到了未知点位于(8,4)的结果。之后,我使用上面的代码进行测试,结果为(7.999978,4.000021710625001)。

接下来,我使用以下数据进行了第二次测试:

P1 = (2,0) r1 = 5.831
P2 = (8,0) r2 = 5.831
P3 = (8,10) r3 = 5.831

手动计算结果为(5,5),使用代码计算的结果也是(5,5)。因此,我认为这段代码是正确的。


非常好用!非常感谢! - Mathijs
不错的解决方案,但只适用于3个点,不能满足原帖的要求。 - luxcem
2
这是2D的,不够准确。你需要使用3D坐标,并找到3个或更多球体的相交点来计算你在建筑物中的位置。但这样做需要非常复杂的数学知识。如果iBeacons位于人类高度以上,则效果最佳。考虑3D因素非常重要。 - coolcool1994
嗨@coolcool1994,上面的方程式是这样制定的,以便球体的中心位于3D的z = 0平面上,请参阅此文章。但我同意这不准确,因为在实际情况下,必须涉及许多变量。还必须记住,信标的信号可能会受到其他信号的干扰,因此从读取信标获得的数字可能不干净。 - Gema Megantara
你如何转换以下步骤:#从ECEF转换回经纬度 #转换为角度 lat = math.degrees(math.asin(triPt[2] / earthR)); lon = math.degrees(math.atan2(triPt[1],triPt[0])); 它们适用于三个点,而不是像你的解决方案那样的二维向量。 - atastrophic
@GemaMegantara,使用三边定位技术的BLE的好解决方案。您能否请清楚我一些事情,您提供的Python实现链接https://gis.stackexchange.com/questions/66/trilateration-using-3-latitude-longitude-points-and-3-distances 是针对GPS的,对吗?我们需要将BLE坐标转换为弧度,还是可以将坐标作为标识ex、i、ey、ez、d和j的方式 - Mahamutha M

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接