2

I am trying to use multiple iBeacons to track the user's location in iOS. I know this can be done (somewhat) using 3 beacons and trilateration, but I would like to do it with two (bilateration). I know that I will likely end up with two answers. Does anyone know of a simple way to accomplish this, given the (x,y) location of the beacons (relative to the room), and an averaged RSSI from each beacon?

I have this code for trilateration that I altered to objective-c from javascript:

- (CGPoint)getTrilaterationWithBeacon1:(BBBeacon *)beacon1 Beacon2:(BBBeacon *)beacon2 Beacon3:(BBBeacon *)beacon3 {
    float xa = beacon1.x;
    float ya = beacon1.y;
    float xb = beacon2.x;
    float yb = beacon2.y;
    float xc = beacon3.x;
    float yc = beacon3.y;
    float ra = beacon1.distance;
    float rb = beacon2.distance;
    float rc = beacon3.distance;

    float S = (pow(xc, 2.) - pow(xb, 2.) + pow(yc, 2.) - pow(yb, 2.) + pow(rb, 2.) - pow(rc, 2.)) / 2.0;
    float T = (pow(xa, 2.) - pow(xb, 2.) + pow(ya, 2.) - pow(yb, 2.) + pow(rb, 2.) - pow(ra, 2.)) / 2.0;
    float y = ((T * (xb - xc)) - (S * (xb - xa))) / (((ya - yb) * (xb - xc)) - ((yc - yb) * (xb - xa)));
    float x = ((y * (ya - yb)) - T) / (xb - xa);

    CGPoint point = CGPointMake(x, y);
    return point;
}
Julian
  • 9,299
  • 5
  • 48
  • 65
rmooney
  • 6,123
  • 3
  • 29
  • 29
  • 2
    You only have two points a(x,y) and b(x,y), not three (you don't have c(x,y)). And you only have two distances, a(r) and b(r), so you need to calculate the intersection of the two circles a(x,y,r) and b(x,y,r). Look for a formula to calculate intersection of two circles. – ChuckCottrill Jan 07 '14 at 16:26
  • 2
    I had the pleasure to play with Qualcomm's beacon, and I think beacons are not good for precise indoor positioning. If you stay in one position the signal strength still alternating, plus it depends on the battery, environment and other things. Beacons are good for telling you, that you are close to something. – Dávid Kaszás Jan 07 '14 at 17:25
  • Agreed with Kaszás: RSSI is an abominable indicator of distance. It will vary wildly with difficult-to-account for factors such as relative antenna orientation, obstructions in the room (particularly people for 2.4GHz signals), interference from other devices, etc, etc. By all means have a go at it, but be prepared for frustration. – ryanm Jan 08 '14 at 11:38

1 Answers1

0

So this is the code I ended up using, thanks to ChuckCottrill's suggestion that I look for a formula to calculate intersection of two circles. It is modified from a C version I found online here: http://paulbourke.net/geometry/circlesphere/tvoght.c

The results are somewhat inconsistent due to the inconsistency of the RSSI values returned from the iBeacons.

I will still need to add code to select the correct point somehow (it gives two results).

- (CGPoint)getBilaterationWithBeacon1:(BBBeacon *)beacon1 Beacon2:(BBBeacon *)beacon2 {
    float x0 = beacon1.locationX;
    float y0 = beacon1.locationY;
    float r0 = beacon1.filteredDistance;
    float x1 = beacon2.locationX;
    float y1 = beacon2.locationY;
    float r1 = beacon2.filteredDistance;

    float a, dx, dy, d, h, rx, ry;
    float x2, y2;

    /* dx and dy are the vertical and horizontal distances between
     * the circle centers.
     */
    dx = x1 - x0;
    dy = y1 - y0;

    /* Determine the straight-line distance between the centers. */
    d = sqrt((dy*dy) + (dx*dx));

    /* Check for solvability. */
    if (d > (r0 + r1)) {
        /* no solution. circles do not intersect. */
        return CGPointMake(-1, -1);
    }
    if (d < abs(r0 - r1)) {
        /* no solution. one circle is contained in the other */
        return CGPointMake(-1, -1);
    }

    /* 'point 2' is the point where the line through the circle
     * intersection points crosses the line between the circle
     * centers.
     */

    /* Determine the distance from point 0 to point 2. */
    a = ((r0*r0) - (r1*r1) + (d*d)) / (2.0 * d) ;

    /* Determine the coordinates of point 2. */
    x2 = x0 + (dx * a/d);
    y2 = y0 + (dy * a/d);

    /* Determine the distance from point 2 to either of the
     * intersection points.
     */
    h = sqrt((r0*r0) - (a*a));

    /* Now determine the offsets of the intersection points from
     * point 2.
     */
    rx = -dy * (h/d);
    ry = dx * (h/d);

    /* Determine the absolute intersection points. */
    float xi = x2 + rx;
    float xi_prime = x2 - rx;
    float yi = y2 + ry;
    float yi_prime = y2 - ry;

    CGPoint point1 = CGPointMake(xi, yi);
    CGPoint point2 = CGPointMake(xi_prime, yi_prime);

    //pick one

    return point2;
}
rmooney
  • 6,123
  • 3
  • 29
  • 29