Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix bearing of the puck being reset on settings change. #1144

Merged
merged 4 commits into from
Feb 23, 2022

Conversation

yunikkk
Copy link
Contributor

@yunikkk yunikkk commented Feb 10, 2022

Summary of changes

The fix resolves the issue with puck bearing, that can jump to zero on when location component settings are changed. The wrong animation looks in the following way :

puck-bearing-jumping.mp4

There are two issues causing such behaviour.
First - we add layer on the map before applying current bearing value. Renderer, which is running in parallel on the background thread, may (and sometimes does) actually run rendering before bearing is applied, thus jumping to the default (0) bearing.
Second - bearing-transition property is not set and defaults to animating during 300 milliseconds. I'm not actually sure about this one since after the first fix it seems not necessary, but iOS for example resets this to zero https://github.com/mapbox/mapbox-maps-ios/blob/9f0e9605b081e45dce808a53f70b5eb0747858ab/Sources/MapboxMaps/Location/Puck/Puck2D.swift#L129. Seems it is some sort of outdated bearing animation in GL native that is not used since we do animations on platforms directly. @mapbox/maps-android please advice here

Pull request checklist:

  • Briefly describe the changes in this PR.
  • Include before/after visuals or gifs if this PR includes visual changes.
  • Write tests for all new functionality. If tests were not written, please explain why.
  • Optimize code for java consumption (@JvmOverloads, @file:JvmName, etc).
  • Add example if relevant.
  • Document any changes to public APIs.
  • Apply changelog label ('breaking change', 'bug 🪲', 'build', 'docs', 'feature 🍏', 'performance ⚡', 'testing 💯') or use the label 'skip changelog'
  • Add an entry inside this element for inclusion in the mapbox-maps-android changelog: <changelog></changelog>.
  • If this PR is a v10.[version] release branch fix / enhancement, merge it to main firstly and then port to v10.[version] release branch.

PRs must be submitted under the terms of our Contributor License Agreement CLA.

@yunikkk yunikkk requested a review from a team as a code owner February 10, 2022 14:59
@yunikkk yunikkk force-pushed the yds-location-bearing-bug branch 2 times, most recently from ccf9287 to 7682290 Compare February 10, 2022 15:01
lastLocation?.let {
updateCurrentPosition(it)
}
updateCurrentBearing(lastBearing)
locationLayerRenderer.addLayers(positionManager)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so this should be called after updateCurrentBearing?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Exactly. Otherwise renderer may run render pass before the updateCurrentBearing will be called thus will use incorrect default zero bearing.
The call sequence becomes :

main thread : locationLayerRenderer.addLayers -> layers are added
render thread : render pass -> no bearing value is set, resets to default
main thread : updateCurrentBearing -> will be applied on the next render pass

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This block will only be executed during init but in your screen recording, it's a long-lasting period. Wondering whether this is the root cause for it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Init is called every time location settings are changed. For the recording I've triggered location component settings change every 700 milliseconds, e.g. in the LocationComponentActivity I've added

    val runnable = object : Runnable {
      override fun run() {
        binding.mapView.location.pulsingMaxRadius = 1f

        binding.mapView.postDelayed(this, 700L)
      }
    }

    binding.mapView.post(runnable)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then it makes sense.

CHANGELOG.md Outdated Show resolved Hide resolved
@@ -8,6 +8,7 @@ internal class LocationIndicatorLayerWrapper(layerId: String) : LocationLayerWra
layerProperties["id"] = Value(layerId)
layerProperties["type"] = Value("location-indicator")
layerProperties["location-transition"] = buildTransition(delay = 0, duration = 0)
layerProperties["bearing-transition"] = buildTransition(delay = 0, duration = 0)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is actually the change I'm not 100% sure about, though it seems that iOS does the same and it disable core bearing animations that otherwise are applied.
Waiting for the comments here

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@alexshalamov perhaps you could comment here?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Location indicator layer properties are transitionable. Bearing and position is interpolated if user sets new value. If interpolation will be always done on SDK level, we could consider making these properties non-transitionable.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We disable transitions on iOS.

Copy link
Contributor Author

@yunikkk yunikkk Feb 14, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the user able to enable it though? Seems there's a public property for that

@yunikkk the location component is built on top of the low level style APIs, so yes, user could overwrite whatever style properties in the runtime if they want to, however I think that's out of the scope of the LocationComponentPlugin.

Currently the bearing of the location indicator layer is driven by the platform animation system, and the gl-native transition should be set to 0, and I believe the default transition should be 0 already?

Copy link
Member

@pengdev pengdev Feb 18, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update: seems the default transition is not 0, as mentioned in the PR description, which is 300 milliseconds in duration. So we should set it specifically to 0.

@yunikkk yunikkk requested a review from kiryldz February 10, 2022 20:13
@kiryldz
Copy link
Contributor

kiryldz commented Feb 11, 2022

Tests are still failing (as well as couple of other bots).

"[interpolate, [exponential, 0.5], [zoom], 0.5, [literal, [$MODEL_SCALE_CONSTANT, $MODEL_SCALE_CONSTANT, $MODEL_SCALE_CONSTANT]], 22.0, [literal, [1.0, 1.0, 1.0]]]",
valueSlot.captured.toString()
)
val value = valueSlot.captured.toString()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

any comments what happens below?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well since we can't compare the whole string (it contains formatted double values that may be slightly different - we compare start and end of the strings, then parse double values and compare relative to ULP (smallest possible double value increment)

CHANGELOG.md Show resolved Hide resolved
Copy link
Contributor

@kiryldz kiryldz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM with nits

@yunikkk yunikkk merged commit e6d089f into main Feb 23, 2022
@yunikkk yunikkk deleted the yds-location-bearing-bug branch February 23, 2022 10:19
@tyofemi tyofemi added this to the V10.4 milestone Mar 25, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants