DanijelHuis / HDAugmentedReality

Augmented Reality component for iOS, written in Swift.
MIT License
480 stars 97 forks source link

Spinning annotations during creation #38

Closed jacogasp closed 7 years ago

jacogasp commented 7 years ago

Hey, I noticed that every time that the ARViewController is presented, all the annotations shortly spin over the screen.

Edit: I think that the bug is in the filtered heading. Every time that the VC is presented, the heading start to increment from zero to the actual heading

 // First real reading after startTracking? Making filter catch up
 if self.catchupHeading && self.heading != 0
 {
   sleep(3)
   self.filteredHeading = self.heading
   self.catchupHeading = false
   print("filtered heading \(self.filteredHeading)")
 }

In principle this section works, but not in reality. I put a timer to check if self.heading takes some time to be updated. What I'm seeing is that sometime filteredHeading is close to zero and sometime and sometime is close to the real heading value.

Edit edit: of course that sleep time is useless over there. At that point self.heading is already a bad value. Post below for the solution.

jacogasp commented 7 years ago

PARTIAL SOLUTION:

change ublic func locationManager(_ manager: CLLocationManager, didUpdateHeading newHeading: CLHeading) with

 public func locationManager(_ manager: CLLocationManager, didUpdateHeading newHeading: CLHeading)
    {
        // filteredHeading is not updated here bcs this is not called too often. filterHeading method should be called manually
        // with display timer.

        if newHeading.headingAccuracy > 15 { // play with this number
            print("Low heading accuracy")
            return
        }

        if newHeading.trueHeading < 0
        {
            self.heading = fmod(newHeading.magneticHeading, 360.0)
        }
        else
        {
            self.heading = fmod(newHeading.trueHeading, 360.0)
        }
    }
DanijelHuis commented 7 years ago

Hm, I had that problem, that is why I used catchupHeading, I tested it and annotations always appear where they should at start, without rotation. This might depend on device or something. The solution might also be enabling calibration(Like on compass app when you open it)

I will definitely test it this week, thx for the report.

DanijelHuis commented 7 years ago

I've added ARTrackingManager.minimumHeadingAccuracy property with default value of 25.

I haven't been able to reproduce the spinning, even when I get headingAccuracy of 25, it doesn't spin, annotations show momentarily and slowly come to true heading as it changes. I will test it more tomorrow on other devices.

I've also added minimumHeadingAccuracyToShowHeadingCalibration property that allows compass calibration, but couldn't test it since it wasn't ever called for me. Default value is 0 - meaning it will never show calibration.

jacogasp commented 7 years ago

To see the spinning of course the phone must heads a direction far from the North, while presenting the view controller.

As you said, it might be an issue related to different devices. I'm using an iPhone SE, unfortunately I don't have any other device to test.

With the update now it seems working like a charm. I will do some more tests but for the moment I would say that the spinning is gone.

jacogasp commented 7 years ago

Hey @DanijelHuis,

what I've seen so far about this solution

if newHeading.headingAccuracy < 0 || newHeading.headingAccuracy > self.minimumHeadingAccuracy
        {
            print("Low heading accuracy")
            return
        } 

is that sometimes the heading accuracy never get below minimumHeadingAccuracy (in this case I'm testing with value 25). So the app gets stuck inside that 'if' waiting for a better heading accuracy, with the result that the annotations are not displayed.

Sometimes happens that putting the app in background and resuming it gets unstuck, showing the annotations again. Sometimes simply nothing happen.

I cannot understand if it's a problem related with my device compass or something else

DanijelHuis commented 7 years ago

Since the compass is obviously very inconsistent, we'll have to find another solution to spinning problem. version 1.1 of the library had something like this: if(fabs(self.filteredHeading - self.heading) > 50) { self.filteredHeading = self.heading } It would make it catchup heading if it was lagging behind, maybe that could help if you put it at top of filterHeading method and set minimumHeadingAccuracy to 120.

Since I cannot reproduce this(I've tried on 4 devices - two iphone 5, ipad 2 mini and ipad 4), It would be really helpful if you could put this: NSLog("\(newHeading.headingAccuracy)") // Don't use print() because it doesn't show time at top of didUpdateHeading and paste results here when spinning happens. From what you are saying it is like you get some very wrong reading at start and then start getting good readings very soon after that. If that is the case maybe I could just not filter heading first few seconds after start.

jacogasp commented 7 years ago

Here what happen leaving all as your last commit, only using minimumHeadingAccuracy = 50.

Disregarding location: age: -0.485254049301147, ha: 3363.0 Disregarding location: age: -52.8836910128593, ha: 65.0 2017-05-23 22:52:19.884185+0200 MonumentFinder[20048:6665206] 180.0 Low heading accuracy 2017-05-23 22:52:19.886312+0200 MonumentFinder[20048:6665206] 25.0 2017-05-23 22:54:16.870303+0200 MonumentFinder[20048:6665206] 30.0 2017-05-23 22:54:16.895072+0200 MonumentFinder[20048:6665206] 30.0 2017-05-23 22:54:16.945322+0200 MonumentFinder[20048:6665206] 30.0 2017-05-23 22:54:16.971603+0200 MonumentFinder[20048:6665206] 30.0 2017-05-23 22:54:16.995182+0200 MonumentFinder[20048:6665206] 30.0 2017-05-23 22:54:17.020308+0200 MonumentFinder[20048:6665206] 30.0 2017-05-23 22:54:17.045099+0200 MonumentFinder[20048:6665206] 30.0 2017-05-23 22:54:17.070262+0200 MonumentFinder[20048:6665206] 30.0 2017-05-23 22:54:17.094876+0200 MonumentFinder[20048:6665206] 30.0 ......

Very first run. I had 30.0 for a while, then little higher and at the end 15.0 I did several runs and it always start with 180.

Changing minimumHeadingAccuracy = 120 leads more on less to the same result.

But I sill have the problem that the annotations are not presented until a wake after putting the app in background. Looking at the log it should be out from if newHeading.headingAccuracy > self.minimumHeadingAccuracy. Then I don't understand what's going on. My code for ARViewController should be fine. I have multiple prints saying how many annotations are effectively loaded and presented. I'm quite sure that I hadn't this problem without the headingAccouracy check

EDIT: tried to remove if newHeading.headingAccuracy > self.minimumHeadingAccuracy and spinning is present at the first launch only few times. Annotations are presented immediately. Putting the app in background and resuming it then the spinning is always present.

P.s. In my app the subclassed ARViewController is the entry controller

EDIT 2: I tried to define catchupHeading as global variable and set to true every time the ViewController disappear. It is properly fired after wake but still spinning present. As you can see at the moment of catchup the heading is (not very) close to 0 o 360 (in this case pointing roughly 120°

2017-05-23 23:58:52.050399+0200 MonumentFinder[20152:6687177] catchup 2017-05-23 23:58:52.050498+0200 MonumentFinder[20152:6687177] 7.62852478027344 2017-05-23 23:59:38.520889+0200 MonumentFinder[20152:6687177] catchup 2017-05-23 23:59:38.520998+0200 MonumentFinder[20152:6687177] 0.341567754745483 2017-05-23 23:59:42.704159+0200 MonumentFinder[20152:6687177] catchup 2017-05-23 23:59:42.704265+0200 MonumentFinder[20152:6687177] 357.713409423828 2017-05-23 23:59:46.654067+0200 MonumentFinder[20152:6687177] catchup 2017-05-23 23:59:46.654347+0200 MonumentFinder[20152:6687177] 0.366164922714233 2017-05-23 23:59:51.354809+0200 MonumentFinder[20152:6687177] catchup 2017-05-23 23:59:51.354912+0200 MonumentFinder[20152:6687177] 357.342651367188 2017-05-23 23:59:55.571819+0200 MonumentFinder[20152:6687177] catchup 2017-05-23 23:59:55.571927+0200 MonumentFinder[20152:6687177] 5.00053405761719 2017-05-23 23:59:59.738374+0200 MonumentFinder[20152:6687177] catchup 2017-05-23 23:59:59.738487+0200 MonumentFinder[20152:6687177] 3.60612463951111 2017-05-24 00:00:06.906040+0200 MonumentFinder[20152:6687177] catchup 2017-05-24 00:00:06.906160+0200 MonumentFinder[20152:6687177] 2.4987325668335

DanijelHuis commented 7 years ago

But I sill have the problem that the annotations are not presented until a wake after putting the app in background.

This should be easy to debug by putting breakpoint and looking at the frames(in ARPresenter.layout...) or maybe by debugging "view hieararchies" in xcode. The only time I had annotations missing from the screen is when my location couldn't be found.

Thx for the logs, I'll try to simulate your headings and see what happens.

DanijelHuis commented 7 years ago

I've added fix to ARTrackingManager, it temporarily disables filtering if heading difference(current heading - previous heading) is greater than 10°. This is done only first 5 seconds after first heading is received.

ARTrackingManager line 269.

jacogasp commented 7 years ago

I'm doing some testing and for the moment it seems to work fine. No spinning annotations and not delay or stuck in the annotations presentation.

jacogasp commented 7 years ago

Ok, the problem with not appearing annotations was definitive my fault, an error in layoutSubview. But the spinning is also definitive gone after the last fix.

I still have some trouble with the compass accuracy but I have the feeling that its related with the device/iOS.

If you want you can close the thread.