Merge lp:~ssweeny/location-service/fix-lp1570878 into lp:location-service/trunk

Proposed by Scott Sweeny
Status: Merged
Approved by: Thomas Voß
Approved revision: 252
Merged at revision: 256
Proposed branch: lp:~ssweeny/location-service/fix-lp1570878
Merge into: lp:location-service/trunk
Diff against target: 162 lines (+55/-15)
6 files modified
include/location_service/com/ubuntu/location/fusion_provider.h (+1/-1)
include/location_service/com/ubuntu/location/newer_or_more_accurate_update_selector.h (+11/-6)
include/location_service/com/ubuntu/location/newer_update_selector.h (+2/-2)
include/location_service/com/ubuntu/location/update_selector.h (+6/-2)
src/location_service/com/ubuntu/location/fusion_provider.cpp (+5/-4)
tests/provider_test.cpp (+30/-0)
To merge this branch: bzr merge lp:~ssweeny/location-service/fix-lp1570878
Reviewer Review Type Date Requested Status
Thomas Voß (community) Approve
Jim Hodapp (community) code Approve
PS Jenkins bot continuous-integration Pending
Review via email: mp+296806@code.launchpad.net

Commit message

Fusion provider: Always use an update that came from the same source as the previous used update (fixes LP: #1570878)

Description of the change

Fix a bug in the fusion provider in which it is too strict about filtering updates which are slightly less accurate than previous updates. The new behavior is to automatically use an update which comes from the same source as the previous used update.

Tested by driving around on local highways and observing that I get position updates around once per second or better.

To post a comment you must log in.
Revision history for this message
Jim Hodapp (jhodapp) wrote :

Looks good to me after discussing a few questions that I had about the code with Scott. I would prefer to not have the value.value syntax but Scott told me it's not possible to avoid that without breaking the provider API.

review: Approve (code)
Revision history for this message
Thomas Voß (thomas-voss) wrote :

LGTM.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'include/location_service/com/ubuntu/location/fusion_provider.h'
2--- include/location_service/com/ubuntu/location/fusion_provider.h 2016-03-10 03:02:31 +0000
3+++ include/location_service/com/ubuntu/location/fusion_provider.h 2016-06-08 22:07:21 +0000
4@@ -48,7 +48,7 @@
5 void stop_velocity_updates() override;
6
7 private:
8- Optional<Update<Position>> last_position;
9+ Optional<WithSource<Update<Position>>> last_position;
10 std::set<Provider::Ptr> providers;
11 std::vector<core::ScopedConnection> connections;
12 };
13
14=== modified file 'include/location_service/com/ubuntu/location/newer_or_more_accurate_update_selector.h'
15--- include/location_service/com/ubuntu/location/newer_or_more_accurate_update_selector.h 2016-03-10 03:02:31 +0000
16+++ include/location_service/com/ubuntu/location/newer_or_more_accurate_update_selector.h 2016-06-08 22:07:21 +0000
17@@ -31,23 +31,28 @@
18 public:
19 typedef std::shared_ptr<NewerOrMoreAccurateUpdateSelector> Ptr;
20
21- Update<Position> select(const Update<Position>& older,
22- const Update<Position>& newer) override
23+ WithSource<Update<Position>> select(const WithSource<Update<Position>>& older,
24+ const WithSource<Update<Position>>& newer) override
25 {
26 // Basically copied this value from the Android fusion provider
27 static const std::chrono::seconds cutoff(11);
28
29+ // If the new position is from the same source as the old one then just use it
30+ if (newer.source == older.source) {
31+ return newer;
32+ }
33+
34 // If the new position is newer by a significant margin then just use it
35- if (newer.when > older.when + cutoff) {
36+ if (newer.value.when > older.value.when + cutoff) {
37 return newer;
38 }
39
40 // Choose the position with the smaller accuracy circle if both have them
41- if (!older.value.accuracy.horizontal)
42+ if (!older.value.value.accuracy.horizontal)
43 return newer;
44- if (!newer.value.accuracy.horizontal)
45+ if (!newer.value.value.accuracy.horizontal)
46 return older;
47- if (newer.value.accuracy.horizontal < older.value.accuracy.horizontal)
48+ if (newer.value.value.accuracy.horizontal < older.value.value.accuracy.horizontal)
49 return newer;
50 else
51 return older;
52
53=== modified file 'include/location_service/com/ubuntu/location/newer_update_selector.h'
54--- include/location_service/com/ubuntu/location/newer_update_selector.h 2016-03-10 03:02:31 +0000
55+++ include/location_service/com/ubuntu/location/newer_update_selector.h 2016-06-08 22:07:21 +0000
56@@ -31,8 +31,8 @@
57 public:
58 typedef std::shared_ptr<NewerUpdateSelector> Ptr;
59
60- Update<Position> select (const Update<Position>& older,
61- const Update<Position>& newer) override
62+ virtual WithSource<Update<Position>> select(const WithSource<Update<Position>>& older,
63+ const WithSource<Update<Position>>& newer) override
64 {
65 return newer;
66 }
67
68=== modified file 'include/location_service/com/ubuntu/location/update_selector.h'
69--- include/location_service/com/ubuntu/location/update_selector.h 2016-03-10 03:02:31 +0000
70+++ include/location_service/com/ubuntu/location/update_selector.h 2016-06-08 22:07:21 +0000
71@@ -27,6 +27,10 @@
72 {
73 namespace location
74 {
75+
76+template<typename T>
77+struct WithSource { std::shared_ptr<Provider> source; T value; };
78+
79 class UpdateSelector
80 {
81 public:
82@@ -36,8 +40,8 @@
83 UpdateSelector& operator=(const UpdateSelector&) = delete;
84 virtual ~UpdateSelector() = default;
85
86- virtual Update<Position> select(const Update<Position>& older,
87- const Update<Position>& newer) = 0;
88+ virtual WithSource<Update<Position>> select(const WithSource<Update<Position>>& older,
89+ const WithSource<Update<Position>>& newer) = 0;
90
91 protected:
92 UpdateSelector() = default;
93
94=== modified file 'src/location_service/com/ubuntu/location/fusion_provider.cpp'
95--- src/location_service/com/ubuntu/location/fusion_provider.cpp 2016-03-10 19:29:45 +0000
96+++ src/location_service/com/ubuntu/location/fusion_provider.cpp 2016-06-08 22:07:21 +0000
97@@ -37,7 +37,6 @@
98 cul::Provider::Requirements::satellites;
99 }
100
101-
102 cul::FusionProvider::FusionProvider(const std::set<location::Provider::Ptr>& providers, const UpdateSelector::Ptr& update_selector)
103 : Provider{all_features(), all_requirements()},
104 providers{providers}
105@@ -46,14 +45,16 @@
106 for (auto provider : providers)
107 {
108 connections.push_back(provider->updates().position.connect(
109- [this, update_selector](const cul::Update<cul::Position>& u)
110+ [this, provider, update_selector](const cul::Update<cul::Position>& u)
111 {
112 // if this is the first update, use it
113 if (!last_position) {
114- mutable_updates().position(*(last_position = u));
115+ mutable_updates().position((*(last_position = WithSource<Update<Position>>{provider, u})).value);
116+
117+ // otherwise use the selector
118 } else {
119 try {
120- mutable_updates().position(*(last_position = update_selector->select(*last_position, u)));
121+ mutable_updates().position((*(last_position = update_selector->select(*last_position, WithSource<Update<Position>>{provider, u}))).value);
122 } catch (const std::exception& e) {
123 LOG(WARNING) << "Error while updating position";
124 }
125
126=== modified file 'tests/provider_test.cpp'
127--- tests/provider_test.cpp 2016-03-08 22:20:10 +0000
128+++ tests/provider_test.cpp 2016-06-08 22:07:21 +0000
129@@ -409,3 +409,33 @@
130 mp2.inject_update(after);
131
132 }
133+
134+TEST(FusionProvider, update_from_same_provider_is_chosen)
135+{
136+ using namespace ::testing;
137+
138+ NiceMock<MockProvider> mp1;
139+
140+ cul::Provider::Ptr p1{std::addressof(mp1), [](cul::Provider*){}};
141+
142+ std::set<cul::Provider::Ptr> providers{p1};
143+
144+ cul::FusionProvider fp{providers, std::make_shared<cul::NewerOrMoreAccurateUpdateSelector>()};
145+
146+ cul::Update<cul::Position> before, after;
147+ before.when = cul::Clock::now() - std::chrono::seconds(5);
148+ before.value = cul::Position(cul::wgs84::Latitude(), cul::wgs84::Longitude(), cul::wgs84::Altitude(), cul::Position::Accuracy::Horizontal{50*cul::units::Meters});
149+ after.when = cul::Clock::now();
150+ after.value = cul::Position(cul::wgs84::Latitude(), cul::wgs84::Longitude(), cul::wgs84::Altitude(), cul::Position::Accuracy::Horizontal{500*cul::units::Meters});
151+
152+ NiceMock<MockEventConsumer> mec;
153+ // We should see the "newer" position even though it's less accurate since
154+ // it came from the same source
155+ EXPECT_CALL(mec, on_new_position(before)).Times(1);
156+ EXPECT_CALL(mec, on_new_position(after)).Times(1);
157+
158+ fp.updates().position.connect([&mec](const cul::Update<cul::Position>& p){mec.on_new_position(p);});
159+
160+ mp1.inject_update(before);
161+ mp1.inject_update(after);
162+}

Subscribers

People subscribed via source and target branches