3

The last couple of days have been full with making calculations and formulas and I'm beginning to lose my mind (a little bit). So now I'm turning to you guys for some insight/help.

Here's the problem; I'm working with bluetooth beacons whom are placed all over an entire floor in a building to make an indoor GPS showcase. You can use your phone to connect with these beacons, which results in receiving your longitude and latitude location from them. These numbers are large float/double variables, looking like this:

  • lat: 52.501288451787076
  • lng: 6.079107635606511

The actual changes happen at the 4th and 5th position after the point. I'm converting these numbers to the Cartesian coordinate system using;

  • x = R * cos(lat) * cos(lon)
  • z = R *sin(lat)

Now the coordinates from this conversion are kind of solid. They are numbers with which I can work with. I use them in a 3d engine (Unity3d) to make a real-time map where you can see where someone is walking.

Now for the actual problem! These beacons are not entirely accurate. These numbers 'jump' up and down even when you lay your phone down. Ranging from, let's assume the same latitude as mentioned above, 52.501280 to 52.501296. If we convert this and use it as coordinates in a 3d engine, the 'avatar' for a user jumps from one position to another (more small jumps than large jumps).

What is a good way to cope with these jumping numbers? I've tried to check for big jumps and ignore those, but the jumps are still too big. A broader check will result in almost no movement, even when a phone is moving. Or is there a better way to convert the lat and long variables for use in a 3d engine?

If there is someone who has had the same problem as me, some mathematical wonder who can give a good conversion/formula to start with or someone who knows what I'm possibly doing wrong then please, help a fellow programmer out.

Siyual
  • 15,390
  • 6
  • 37
  • 57
Amacoder
  • 173
  • 1
  • 13
  • 3
    Don't know if I understand the problem correctly... You might think about a [Moving Average](https://en.wikipedia.org/wiki/Moving_average). – Shnugo Dec 03 '15 at 10:47
  • what an interesting question. And a big YES to @Shnugo 's advice. I think you could further refine your movement by using unity's Input.acceleration or Input.gyro.userAcceleration . The latter is what I use and it works perfectly (I needed to enable it first via code on Android). So if you are planning to go hardcore you may check gyro acceleration every frame and... mm... probably 1. average the acceleration AND the Moving Average algorithm, or 2. use the acceleration as a coefficient to the latter. But again, I think you'd be fine with the Moving Average. – Nika Kasradze Dec 03 '15 at 12:13
  • I will definitely give the Moving Average a shot. Using acceleration was something I thought about but never actually tried. Thanks for the input. – Amacoder Dec 04 '15 at 14:05

1 Answers1

1

Moving Average

You could use this: (Taken here: https://stackoverflow.com/a/1305/5089204)

Attention: Please read the comments to this class as this implementation has some flaws... It's just for quick test and show...

    public class LimitedQueue<T> : Queue<T> {
        private int limit = -1;

        public int Limit {
            get { return limit; }
            set { limit = value; }
        }

        public LimitedQueue(int limit)
            : base(limit) {
            this.Limit = limit;
        }

        public new void Enqueue(T item) {
            if (this.Count >= this.Limit) {
                this.Dequeue();
            }
            base.Enqueue(item);
        }
    }

Just test it like this:

        var queue = new LimitedQueue<float>(4);

        queue.Enqueue(52.501280f);
        var avg1 = queue.Average(); //52.50128
        queue.Enqueue(52.501350f);
        var avg2 = queue.Average(); //52.5013161
        queue.Enqueue(52.501140f);
        var avg3 = queue.Average(); //52.50126
        queue.Enqueue(52.501022f);
        var avg4 = queue.Average(); //52.5011978
        queue.Enqueue(52.501635f);
        var avg5 = queue.Average(); //52.50129
        queue.Enqueue(52.501500f);
        var avg6 = queue.Average(); //52.5013237
        queue.Enqueue(52.501505f);
        var avg7 = queue.Average(); //52.5014153
        queue.Enqueue(52.501230f);
        var avg8 = queue.Average(); //52.50147

The limited queue will not grow... You just define the count of elements you want to use (in this case I specified 4). The 5th element pushes the first out and so on...

The average will always be a smooth sliding :-)

Community
  • 1
  • 1
Shnugo
  • 62,351
  • 7
  • 42
  • 92
  • Nice. Will get back if and when results. – Amacoder Dec 04 '15 at 14:07
  • It did work, had to change it a bit to work with the api though. But the problem is the api is so much crap plus the beacons are still so inaccurate that even the moving average algorithm doesn't bare it's fruits. Guess I'll have to wait till the developers of the api improve the Beacon software and api. Will accept your answer as solved because the problem lies with the api now. – Amacoder Dec 11 '15 at 17:22
  • @Amacoder glad to read, that this could solve your issue. Please allow me one hint: I visited your profile and found that you accepted almost all your questions, this is great. But - if you don't mind - please read [this](http://meta.stackexchange.com/q/686/311071). You did not upvote there (and here)... An up-vote is important for badges and reputation. All profs giving answers here are addicted to badges and rep points :-) – Shnugo Dec 11 '15 at 17:53