Merge lp:~ssweeny/location-service/fusion-provider.15.04 into lp:location-service/15.04

Proposed by Scott Sweeny
Status: Superseded
Proposed branch: lp:~ssweeny/location-service/fusion-provider.15.04
Merge into: lp:location-service/15.04
Diff against target: 771 lines (+551/-122)
11 files modified
include/location_service/com/ubuntu/location/fusion_provider.h (+59/-0)
include/location_service/com/ubuntu/location/fusion_provider_selection_policy.h (+39/-0)
include/location_service/com/ubuntu/location/newer_or_more_accurate_update_selector.h (+60/-0)
include/location_service/com/ubuntu/location/newer_update_selector.h (+45/-0)
include/location_service/com/ubuntu/location/update_selector.h (+49/-0)
src/location_service/com/ubuntu/location/CMakeLists.txt (+2/-0)
src/location_service/com/ubuntu/location/fusion_provider.cpp (+141/-0)
src/location_service/com/ubuntu/location/fusion_provider_selection_policy.cpp (+26/-0)
src/location_service/com/ubuntu/location/non_selecting_provider_selection_policy.cpp (+3/-120)
src/location_service/com/ubuntu/location/service/default_configuration.cpp (+2/-2)
tests/provider_test.cpp (+125/-0)
To merge this branch: bzr merge lp:~ssweeny/location-service/fusion-provider.15.04
Reviewer Review Type Date Requested Status
Thomas Voß (community) Approve
Konrad Zapałowicz (community) Needs Fixing
Review via email: mp+287242@code.launchpad.net

This proposal has been superseded by a proposal from 2016-04-05.

Commit message

Use a fusion engine provider to generate higher quality position updates

Description of the change

Use a fusion engine provider to generate higher quality position updates

To post a comment you must log in.
Revision history for this message
Thomas Voß (thomas-voss) wrote :

Thanks for the changes. Some design feedback first: I think you only need a FusioningProvider and you can get rid of BagOfProviders by defining a helper interface:

class UpdateSelector
{
public:
  virtual void Update<Position> select(const Update<Position>& old, const Update<Position>& new) = 0
};

and passing an implementation of UpdateSelector to the FusioningProvider ctor. The BagOfProviders behavior can then be achieved by having:

class AlwaysSelectNewUpdate : public UpdateSelector
{
public:
  void Update<Position> select(const Update<Position>&, const Update<Position>& new) override
  {
    return new;
  }
};

The is_better_than predicate would then end up being an implementation of UpdateSelector, along the lines of:

class SignificantlyNewerOrMoreAccurateSelector : public UpdateSelector
{
public:
   ...
};

Whenever a new session is constructed, we could select between the current or the new behavior by just passing a different implementation.

One more comment inline.

review: Needs Fixing
220. By Scott Sweeny

FusionProvider: make last_position optional for a more robust test of its validity

221. By Scott Sweeny

Per review comments, eliminate BagOfProviders and use a helper to select update strategies for FusionProvider

Revision history for this message
Konrad Zapałowicz (kzapalowicz) wrote :

Good stuff just two places where reference could be considered.

review: Needs Fixing
222. By Scott Sweeny

Pass UpdateSelectors and return Updates by reference

223. By Scott Sweeny

Remove a couple of debug statements

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

Minor remaining niggles inline.

review: Needs Fixing
224. By Scott Sweeny

Small changes addressing review comments

Revision history for this message
Scott Sweeny (ssweeny) wrote :

One of the changes doesn't seem to work, but the others are done.

Revision history for this message
Scott Sweeny (ssweeny) wrote :

> One of the changes doesn't seem to work, but the others are done.

The way LP displays the comments is confusing since the code is updated so I'm going to repeat myself here:

For the changes in fusion_provider.cpp:

These two changes don't work for me. The tests freeze up with a "this->is_initialized()" assertion failure when I use '*' notation with last_position, but the compile fails when I don't use it.

225. By Scott Sweeny

Prettify the last_position update code

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

LGTM.

review: Approve

Unmerged revisions

225. By Scott Sweeny

Prettify the last_position update code

224. By Scott Sweeny

Small changes addressing review comments

223. By Scott Sweeny

Remove a couple of debug statements

222. By Scott Sweeny

Pass UpdateSelectors and return Updates by reference

221. By Scott Sweeny

Per review comments, eliminate BagOfProviders and use a helper to select update strategies for FusionProvider

220. By Scott Sweeny

FusionProvider: make last_position optional for a more robust test of its validity

219. By Scott Sweeny

Add selection policy for fusion provider and use it by default

218. By Scott Sweeny

Add test for FusionProvider

217. By Scott Sweeny

Add fusion provider based on BagOfProviders

216. By Scott Sweeny

Factor BagOfProviders out into its own class so it can be reused

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added file 'include/location_service/com/ubuntu/location/fusion_provider.h'
2--- include/location_service/com/ubuntu/location/fusion_provider.h 1970-01-01 00:00:00 +0000
3+++ include/location_service/com/ubuntu/location/fusion_provider.h 2016-03-10 19:30:01 +0000
4@@ -0,0 +1,59 @@
5+/*
6+ * Copyright © 2016 Canonical Ltd.
7+ *
8+ * This program is free software: you can redistribute it and/or modify it
9+ * under the terms of the GNU Lesser General Public License version 3,
10+ * as published by the Free Software Foundation.
11+ *
12+ * This program is distributed in the hope that it will be useful,
13+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+ * GNU Lesser General Public License for more details.
16+ *
17+ * You should have received a copy of the GNU Lesser General Public License
18+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
19+ *
20+ * Authored by: Scott Sweeny <scott.sweeny@canonical.com
21+ */
22+#ifndef LOCATION_SERVICE_COM_UBUNTU_LOCATION_FUSION_PROVIDER_H
23+#define LOCATION_SERVICE_COM_UBUNTU_LOCATION_FUSION_PROVIDER_H
24+
25+#include <com/ubuntu/location/provider.h>
26+#include <com/ubuntu/location/provider_selection_policy.h>
27+#include <com/ubuntu/location/update_selector.h>
28+
29+namespace com
30+{
31+namespace ubuntu
32+{
33+namespace location
34+{
35+class FusionProvider : public Provider
36+{
37+public:
38+ typedef std::shared_ptr<FusionProvider> Ptr;
39+
40+ FusionProvider(const std::set<Provider::Ptr>& providers, const UpdateSelector::Ptr& update_selector);
41+
42+ bool matches_criteria(const Criteria &criteria) override;
43+ void on_wifi_and_cell_reporting_state_changed(location::WifiAndCellIdReportingState state) override;
44+ void on_reference_location_updated(const Update<Position>& position) override;
45+ void on_reference_velocity_updated(const Update<Velocity>& velocity) override;
46+ void on_reference_heading_updated(const Update<Heading>& heading) override;
47+ void start_position_updates() override;
48+ void stop_position_updates() override;
49+ void start_heading_updates() override;
50+ void stop_heading_updates() override;
51+ void start_velocity_updates() override;
52+ void stop_velocity_updates() override;
53+
54+private:
55+ Optional<Update<Position>> last_position;
56+ std::set<Provider::Ptr> providers;
57+ std::vector<core::ScopedConnection> connections;
58+};
59+}
60+}
61+}
62+
63+#endif // LOCATION_SERVICE_COM_UBUNTU_LOCATION_FUSION_PROVIDER_H
64
65=== added file 'include/location_service/com/ubuntu/location/fusion_provider_selection_policy.h'
66--- include/location_service/com/ubuntu/location/fusion_provider_selection_policy.h 1970-01-01 00:00:00 +0000
67+++ include/location_service/com/ubuntu/location/fusion_provider_selection_policy.h 2016-03-10 19:30:01 +0000
68@@ -0,0 +1,39 @@
69+/*
70+ * Copyright © 2016 Canonical Ltd.
71+ *
72+ * This program is free software: you can redistribute it and/or modify it
73+ * under the terms of the GNU Lesser General Public License version 3,
74+ * as published by the Free Software Foundation.
75+ *
76+ * This program is distributed in the hope that it will be useful,
77+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
78+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
79+ * GNU Lesser General Public License for more details.
80+ *
81+ * You should have received a copy of the GNU Lesser General Public License
82+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
83+ *
84+ * Authored by: Scott Sweeny <scott.sweeny@canonical.com
85+ */
86+#ifndef COM_UBUNTU_LOCATION_FUSION_PROVIDER_SELECTION_POLICY_H
87+#define COM_UBUNTU_LOCATION_FUSION_PROVIDER_SELECTION_POILCY_H
88+
89+#include <com/ubuntu/location/provider_selection_policy.h>
90+
91+namespace com
92+{
93+namespace ubuntu
94+{
95+namespace location
96+{
97+// This policy selects all providers, supplying them in the form of a fusion
98+// provider for higher quality position updates
99+struct FusionProviderSelectionPolicy : public ProviderSelectionPolicy
100+{
101+ ProviderSelection determine_provider_selection_for_criteria(const Criteria &criteria, const ProviderEnumerator &enumerator);
102+};
103+}
104+}
105+}
106+
107+#endif // COM_UBUNTU_LOCATION_FUSION_PROVIDER_SELECTION_POILCY_H
108
109=== added file 'include/location_service/com/ubuntu/location/newer_or_more_accurate_update_selector.h'
110--- include/location_service/com/ubuntu/location/newer_or_more_accurate_update_selector.h 1970-01-01 00:00:00 +0000
111+++ include/location_service/com/ubuntu/location/newer_or_more_accurate_update_selector.h 2016-03-10 19:30:01 +0000
112@@ -0,0 +1,60 @@
113+/*
114+ * Copyright © 2016 Canonical Ltd.
115+ *
116+ * This program is free software: you can redistribute it and/or modify it
117+ * under the terms of the GNU Lesser General Public License version 3,
118+ * as published by the Free Software Foundation.
119+ *
120+ * This program is distributed in the hope that it will be useful,
121+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
122+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
123+ * GNU Lesser General Public License for more details.
124+ *
125+ * You should have received a copy of the GNU Lesser General Public License
126+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
127+ *
128+ * Authored by: Scott Sweeny <scott.sweeny@canonical.com
129+ */
130+#ifndef LOCATION_SERVICE_COM_UBUNTU_LOCATIONNEWER_OR_MORE_ACCURATE_UPDATE_SELECTOR_H
131+#define LOCATION_SERVICE_COM_UBUNTU_LOCATIONNEWER_OR_MORE_ACCURATE_UPDATE_SELECTOR_H
132+
133+#include <com/ubuntu/location/update_selector.h>
134+
135+namespace com
136+{
137+namespace ubuntu
138+{
139+namespace location
140+{
141+class NewerOrMoreAccurateUpdateSelector : public UpdateSelector
142+{
143+public:
144+ typedef std::shared_ptr<NewerOrMoreAccurateUpdateSelector> Ptr;
145+
146+ Update<Position> select(const Update<Position>& older,
147+ const Update<Position>& newer) override
148+ {
149+ // Basically copied this value from the Android fusion provider
150+ static const std::chrono::seconds cutoff(11);
151+
152+ // If the new position is newer by a significant margin then just use it
153+ if (newer.when > older.when + cutoff) {
154+ return newer;
155+ }
156+
157+ // Choose the position with the smaller accuracy circle if both have them
158+ if (!older.value.accuracy.horizontal)
159+ return newer;
160+ if (!newer.value.accuracy.horizontal)
161+ return older;
162+ if (newer.value.accuracy.horizontal < older.value.accuracy.horizontal)
163+ return newer;
164+ else
165+ return older;
166+ }
167+};
168+}
169+}
170+}
171+#endif // LOCATION_SERVICE_COM_UBUNTU_LOCATIONNEWER_OR_MORE_ACCURATE_UPDATE_SELECTOR_H
172+
173
174=== added file 'include/location_service/com/ubuntu/location/newer_update_selector.h'
175--- include/location_service/com/ubuntu/location/newer_update_selector.h 1970-01-01 00:00:00 +0000
176+++ include/location_service/com/ubuntu/location/newer_update_selector.h 2016-03-10 19:30:01 +0000
177@@ -0,0 +1,45 @@
178+/*
179+ * Copyright © 2016 Canonical Ltd.
180+ *
181+ * This program is free software: you can redistribute it and/or modify it
182+ * under the terms of the GNU Lesser General Public License version 3,
183+ * as published by the Free Software Foundation.
184+ *
185+ * This program is distributed in the hope that it will be useful,
186+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
187+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
188+ * GNU Lesser General Public License for more details.
189+ *
190+ * You should have received a copy of the GNU Lesser General Public License
191+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
192+ *
193+ * Authored by: Scott Sweeny <scott.sweeny@canonical.com
194+ */
195+#ifndef LOCATION_SERVICE_COM_UBUNTU_LOCATION_ALWAYS_SELECT_NEW_UPDATE_H
196+#define LOCATION_SERVICE_COM_UBUNTU_LOCATION_ALWAYS_SELECT_NEW_UPDATE_H
197+
198+#include <com/ubuntu/location/update_selector.h>
199+
200+namespace com
201+{
202+namespace ubuntu
203+{
204+namespace location
205+{
206+class NewerUpdateSelector : public UpdateSelector
207+{
208+public:
209+ typedef std::shared_ptr<NewerUpdateSelector> Ptr;
210+
211+ Update<Position> select (const Update<Position>& older,
212+ const Update<Position>& newer) override
213+ {
214+ return newer;
215+ }
216+};
217+}
218+}
219+}
220+
221+#endif // LOCATION_SERVICE_COM_UBUNTU_LOCATION_ALWAYS_SELECT_NEW_UPDATE_H
222+
223
224=== added file 'include/location_service/com/ubuntu/location/update_selector.h'
225--- include/location_service/com/ubuntu/location/update_selector.h 1970-01-01 00:00:00 +0000
226+++ include/location_service/com/ubuntu/location/update_selector.h 2016-03-10 19:30:01 +0000
227@@ -0,0 +1,49 @@
228+/*
229+ * Copyright © 2016 Canonical Ltd.
230+ *
231+ * This program is free software: you can redistribute it and/or modify it
232+ * under the terms of the GNU Lesser General Public License version 3,
233+ * as published by the Free Software Foundation.
234+ *
235+ * This program is distributed in the hope that it will be useful,
236+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
237+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
238+ * GNU Lesser General Public License for more details.
239+ *
240+ * You should have received a copy of the GNU Lesser General Public License
241+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
242+ *
243+ * Authored by: Scott Sweeny <scott.sweeny@canonical.com
244+ */
245+#ifndef LOCATION_SERVICE_COM_UBUNTU_LOCATION_UPDATE_SELECTOR_H
246+#define LOCATION_SERVICE_COM_UBUNTU_LOCATION_UPDATE_SELECTOR_H
247+
248+#include <com/ubuntu/location/update.h>
249+#include <com/ubuntu/location/position.h>
250+
251+namespace com
252+{
253+namespace ubuntu
254+{
255+namespace location
256+{
257+class UpdateSelector
258+{
259+public:
260+ typedef std::shared_ptr<UpdateSelector> Ptr;
261+
262+ UpdateSelector(const UpdateSelector&) = delete;
263+ UpdateSelector& operator=(const UpdateSelector&) = delete;
264+ virtual ~UpdateSelector() = default;
265+
266+ virtual Update<Position> select(const Update<Position>& older,
267+ const Update<Position>& newer) = 0;
268+
269+protected:
270+ UpdateSelector() = default;
271+};
272+}
273+}
274+}
275+#endif // LOCATION_SERVICE_COM_UBUNTU_LOCATION_UPDATE_SELECTOR_H
276+
277
278=== modified file 'src/location_service/com/ubuntu/location/CMakeLists.txt'
279--- src/location_service/com/ubuntu/location/CMakeLists.txt 2015-11-26 08:28:38 +0000
280+++ src/location_service/com/ubuntu/location/CMakeLists.txt 2016-03-10 19:30:01 +0000
281@@ -16,10 +16,12 @@
282 ${UBUNTU_LOCATION_SERVICE_PUBLIC_HEADERS}
283
284 default_provider_selection_policy.cpp
285+ fusion_provider_selection_policy.cpp
286 non_selecting_provider_selection_policy.cpp
287
288 criteria.cpp
289 engine.cpp
290+ fusion_provider.cpp
291 init_and_shutdown.cpp
292 position.cpp
293 provider.cpp
294
295=== added file 'src/location_service/com/ubuntu/location/fusion_provider.cpp'
296--- src/location_service/com/ubuntu/location/fusion_provider.cpp 1970-01-01 00:00:00 +0000
297+++ src/location_service/com/ubuntu/location/fusion_provider.cpp 2016-03-10 19:30:01 +0000
298@@ -0,0 +1,141 @@
299+/*
300+ * Copyright © 2016 Canonical Ltd.
301+ *
302+ * This program is free software: you can redistribute it and/or modify it
303+ * under the terms of the GNU Lesser General Public License version 3,
304+ * as published by the Free Software Foundation.
305+ *
306+ * This program is distributed in the hope that it will be useful,
307+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
308+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
309+ * GNU Lesser General Public License for more details.
310+ *
311+ * You should have received a copy of the GNU Lesser General Public License
312+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
313+ *
314+ * Authored by: Scott Sweeny <scott.sweeny@canonical.com
315+ */
316+ #include <com/ubuntu/location/fusion_provider.h>
317+ #include <com/ubuntu/location/logging.h>
318+ #include <com/ubuntu/location/update.h>
319+
320+namespace cu = com::ubuntu;
321+namespace cul = com::ubuntu::location;
322+
323+cul::Provider::Features all_features()
324+{
325+ return cul::Provider::Features::position |
326+ cul::Provider::Features::heading |
327+ cul::Provider::Features::velocity;
328+}
329+
330+cul::Provider::Requirements all_requirements()
331+{
332+ return cul::Provider::Requirements::cell_network |
333+ cul::Provider::Requirements::data_network |
334+ cul::Provider::Requirements::monetary_spending |
335+ cul::Provider::Requirements::satellites;
336+}
337+
338+
339+cul::FusionProvider::FusionProvider(const std::set<location::Provider::Ptr>& providers, const UpdateSelector::Ptr& update_selector)
340+ : Provider{all_features(), all_requirements()},
341+ providers{providers}
342+{
343+
344+ for (auto provider : providers)
345+ {
346+ connections.push_back(provider->updates().position.connect(
347+ [this, update_selector](const cul::Update<cul::Position>& u)
348+ {
349+ // if this is the first update, use it
350+ if (!last_position) {
351+ mutable_updates().position(*(last_position = u));
352+ } else {
353+ try {
354+ mutable_updates().position(*(last_position = update_selector->select(*last_position, u)));
355+ } catch (const std::exception& e) {
356+ LOG(WARNING) << "Error while updating position";
357+ }
358+ }
359+ }));
360+ connections.push_back(provider->updates().heading.connect(
361+ [this](const cul::Update<cul::Heading>& u)
362+ {
363+ mutable_updates().heading(u);
364+ }));
365+ connections.push_back(provider->updates().velocity.connect(
366+ [this](const cul::Update<cul::Velocity>& u)
367+ {
368+ mutable_updates().velocity(u);
369+ }));
370+ }
371+
372+}
373+
374+// We always match :)
375+bool cul::FusionProvider::matches_criteria(const cul::Criteria&)
376+{
377+ return true;
378+}
379+
380+// We forward all events to the other providers.
381+void cul::FusionProvider::on_wifi_and_cell_reporting_state_changed(cul::WifiAndCellIdReportingState state)
382+{
383+ for (auto provider : providers)
384+ provider->on_wifi_and_cell_reporting_state_changed(state);
385+}
386+
387+void cul::FusionProvider::on_reference_location_updated(const cul::Update<cul::Position>& position)
388+{
389+ for (auto provider : providers)
390+ provider->on_reference_location_updated(position);
391+}
392+
393+void cul::FusionProvider::on_reference_velocity_updated(const cul::Update<cul::Velocity>& velocity)
394+{
395+ for (auto provider : providers)
396+ provider->on_reference_velocity_updated(velocity);
397+}
398+
399+void cul::FusionProvider::on_reference_heading_updated(const cul::Update<cul::Heading>& heading)
400+{
401+ for (auto provider : providers)
402+ provider->on_reference_heading_updated(heading);
403+}
404+
405+void cul::FusionProvider::start_position_updates()
406+{
407+ for (auto provider : providers)
408+ provider->state_controller()->start_position_updates();
409+}
410+
411+void cul::FusionProvider::stop_position_updates()
412+{
413+ for (auto provider : providers)
414+ provider->state_controller()->stop_position_updates();
415+}
416+
417+void cul::FusionProvider::start_heading_updates()
418+{
419+ for (auto provider : providers)
420+ provider->state_controller()->start_heading_updates();
421+}
422+
423+void cul::FusionProvider::stop_heading_updates()
424+{
425+ for (auto provider : providers)
426+ provider->state_controller()->stop_heading_updates();
427+}
428+
429+void cul::FusionProvider::start_velocity_updates()
430+{
431+ for (auto provider : providers)
432+ provider->state_controller()->start_velocity_updates();
433+}
434+
435+void cul::FusionProvider::stop_velocity_updates()
436+{
437+ for (auto provider : providers)
438+ provider->state_controller()->stop_velocity_updates();
439+}
440
441=== added file 'src/location_service/com/ubuntu/location/fusion_provider_selection_policy.cpp'
442--- src/location_service/com/ubuntu/location/fusion_provider_selection_policy.cpp 1970-01-01 00:00:00 +0000
443+++ src/location_service/com/ubuntu/location/fusion_provider_selection_policy.cpp 2016-03-10 19:30:01 +0000
444@@ -0,0 +1,26 @@
445+#include <com/ubuntu/location/fusion_provider.h>
446+#include <com/ubuntu/location/fusion_provider_selection_policy.h>
447+#include <com/ubuntu/location/newer_or_more_accurate_update_selector.h>
448+
449+namespace location = com::ubuntu::location;
450+
451+location::ProviderSelection location::FusionProviderSelectionPolicy::determine_provider_selection_for_criteria(
452+ const location::Criteria&,
453+ const location::ProviderEnumerator& enumerator)
454+{
455+ // We put all providers in a set.
456+ std::set<location::Provider::Ptr> bag;
457+ enumerator.for_each_provider([&bag](const location::Provider::Ptr& provider)
458+ {
459+ bag.insert(provider);
460+ });
461+
462+ auto fusion_providers = std::make_shared<location::FusionProvider>(bag, std::make_shared<location::NewerOrMoreAccurateUpdateSelector>());
463+
464+ return location::ProviderSelection
465+ {
466+ fusion_providers, // position
467+ fusion_providers, // heading
468+ fusion_providers, // velocity
469+ };
470+}
471
472=== modified file 'src/location_service/com/ubuntu/location/non_selecting_provider_selection_policy.cpp'
473--- src/location_service/com/ubuntu/location/non_selecting_provider_selection_policy.cpp 2015-11-18 09:40:10 +0000
474+++ src/location_service/com/ubuntu/location/non_selecting_provider_selection_policy.cpp 2016-03-10 19:30:01 +0000
475@@ -17,130 +17,13 @@
476 */
477
478 #include <com/ubuntu/location/non_selecting_provider_selection_policy.h>
479+#include <com/ubuntu/location/fusion_provider.h>
480+#include <com/ubuntu/location/newer_update_selector.h>
481
482 #include <set>
483
484 namespace location = com::ubuntu::location;
485
486-namespace
487-{
488-
489-location::Provider::Features all_features()
490-{
491- return location::Provider::Features::position |
492- location::Provider::Features::heading |
493- location::Provider::Features::velocity;
494-}
495-
496-location::Provider::Requirements all_requirements()
497-{
498- return location::Provider::Requirements::cell_network |
499- location::Provider::Requirements::data_network |
500- location::Provider::Requirements::monetary_spending |
501- location::Provider::Requirements::satellites;
502-}
503-
504-// A simple helper that takes a set of existing providers
505-// and maps calls to each of them.
506-struct BagOfProviders : public location::Provider
507-{
508- BagOfProviders(const std::set<location::Provider::Ptr>& providers)
509- : location::Provider{all_features(), all_requirements()},
510- providers{providers}
511- {
512- // We connect to all updates of each provider.
513- for (auto provider : BagOfProviders::providers)
514- {
515- connections.push_back(provider->updates().position.connect([this](const location::Update<location::Position>& update)
516- {
517- mutable_updates().position(update);
518- }));
519-
520- connections.push_back(provider->updates().heading.connect([this](const location::Update<location::Heading>& update)
521- {
522- mutable_updates().heading(update);
523- }));
524-
525- connections.push_back(provider->updates().velocity.connect([this](const location::Update<location::Velocity>& update)
526- {
527- mutable_updates().velocity(update);
528- }));
529- }
530-
531- }
532-
533- // We always match :)
534- bool matches_criteria(const location::Criteria&) override
535- {
536- return true;
537- }
538-
539- // We forward all events to the other providers.
540- void on_wifi_and_cell_reporting_state_changed(location::WifiAndCellIdReportingState state) override
541- {
542- for (auto provider : providers)
543- provider->on_wifi_and_cell_reporting_state_changed(state);
544- }
545-
546- void on_reference_location_updated(const location::Update<location::Position>& position) override
547- {
548- for (auto provider : providers)
549- provider->on_reference_location_updated(position);
550- }
551-
552- void on_reference_velocity_updated(const location::Update<location::Velocity>& velocity) override
553- {
554- for (auto provider : providers)
555- provider->on_reference_velocity_updated(velocity);
556- }
557-
558- void on_reference_heading_updated(const location::Update<location::Heading>& heading) override
559- {
560- for (auto provider : providers)
561- provider->on_reference_heading_updated(heading);
562- }
563-
564- void start_position_updates() override
565- {
566- for (auto provider : providers)
567- provider->state_controller()->start_position_updates();
568- }
569-
570- void stop_position_updates() override
571- {
572- for (auto provider : providers)
573- provider->state_controller()->stop_position_updates();
574- }
575-
576- void start_heading_updates() override
577- {
578- for (auto provider : providers)
579- provider->state_controller()->start_heading_updates();
580- }
581-
582- void stop_heading_updates() override
583- {
584- for (auto provider : providers)
585- provider->state_controller()->stop_heading_updates();
586- }
587-
588- void start_velocity_updates() override
589- {
590- for (auto provider : providers)
591- provider->state_controller()->start_velocity_updates();
592- }
593-
594- void stop_velocity_updates() override
595- {
596- for (auto provider : providers)
597- provider->state_controller()->stop_velocity_updates();
598- }
599-
600- std::set<location::Provider::Ptr> providers;
601- std::vector<core::ScopedConnection> connections;
602-};
603-}
604-
605 location::ProviderSelection location::NonSelectingProviderSelectionPolicy::determine_provider_selection_for_criteria(
606 const location::Criteria&,
607 const location::ProviderEnumerator& enumerator)
608@@ -152,7 +35,7 @@
609 bag.insert(provider);
610 });
611
612- auto bag_of_providers = std::make_shared<BagOfProviders>(bag);
613+ auto bag_of_providers = std::make_shared<FusionProvider>(bag, std::make_shared<NewerUpdateSelector>());
614
615 // Our bag of providers is responsible for delivering position/heading/velocity updates.
616 return location::ProviderSelection
617
618=== modified file 'src/location_service/com/ubuntu/location/service/default_configuration.cpp'
619--- src/location_service/com/ubuntu/location/service/default_configuration.cpp 2014-11-14 11:33:05 +0000
620+++ src/location_service/com/ubuntu/location/service/default_configuration.cpp 2016-03-10 19:30:01 +0000
621@@ -20,7 +20,7 @@
622 #include <com/ubuntu/location/service/trust_store_permission_manager.h>
623
624 #include <com/ubuntu/location/engine.h>
625-#include <com/ubuntu/location/non_selecting_provider_selection_policy.h>
626+#include <com/ubuntu/location/fusion_provider_selection_policy.h>
627
628 namespace cul = com::ubuntu::location;
629 namespace culs = com::ubuntu::location::service;
630@@ -39,7 +39,7 @@
631
632 cul::ProviderSelectionPolicy::Ptr culs::DefaultConfiguration::the_provider_selection_policy()
633 {
634- return std::make_shared<cul::NonSelectingProviderSelectionPolicy>();
635+ return std::make_shared<cul::FusionProviderSelectionPolicy>();
636 }
637
638 std::set<cul::Provider::Ptr> culs::DefaultConfiguration::the_provider_set(
639
640=== modified file 'tests/provider_test.cpp'
641--- tests/provider_test.cpp 2015-01-21 20:04:56 +0000
642+++ tests/provider_test.cpp 2016-03-10 19:30:01 +0000
643@@ -284,3 +284,128 @@
644 mp2.inject_update(cul::Update<cul::Heading>());
645 mp3.inject_update(cul::Update<cul::Velocity>());
646 }
647+
648+#include <com/ubuntu/location/fusion_provider.h>
649+#include <com/ubuntu/location/newer_or_more_accurate_update_selector.h>
650+
651+TEST(FusionProvider, start_and_stop_of_updates_propagates_to_correct_providers)
652+{
653+ using namespace ::testing;
654+
655+ NiceMock<MockProvider> mp1, mp2, mp3;
656+ EXPECT_CALL(mp1, start_position_updates()).Times(Exactly(1));
657+ EXPECT_CALL(mp1, stop_position_updates()).Times(Exactly(1));
658+ EXPECT_CALL(mp2, start_heading_updates()).Times(Exactly(1));
659+ EXPECT_CALL(mp2, stop_heading_updates()).Times(Exactly(1));
660+ EXPECT_CALL(mp3, start_velocity_updates()).Times(Exactly(1));
661+ EXPECT_CALL(mp3, stop_velocity_updates()).Times(Exactly(1));
662+
663+ cul::Provider::Ptr p1{std::addressof(mp1), [](cul::Provider*){}};
664+ cul::Provider::Ptr p2{std::addressof(mp2), [](cul::Provider*){}};
665+ cul::Provider::Ptr p3{std::addressof(mp3), [](cul::Provider*){}};
666+
667+ cul::ProviderSelection selection{p1, p2, p3};
668+ std::set<cul::Provider::Ptr> providers{p1, p2, p3};
669+
670+ //cul::FusionProvider pp{selection};
671+ cul::FusionProvider fp{providers, std::make_shared<cul::NewerOrMoreAccurateUpdateSelector>()};
672+
673+ fp.start_position_updates();
674+ fp.stop_position_updates();
675+
676+ fp.start_heading_updates();
677+ fp.stop_heading_updates();
678+
679+ fp.start_velocity_updates();
680+ fp.stop_velocity_updates();
681+}
682+
683+TEST(FusionProvider, update_signals_are_routed_from_correct_providers)
684+{
685+ using namespace ::testing;
686+
687+ NiceMock<MockProvider> mp1, mp2, mp3;
688+
689+ cul::Provider::Ptr p1{std::addressof(mp1), [](cul::Provider*){}};
690+ cul::Provider::Ptr p2{std::addressof(mp2), [](cul::Provider*){}};
691+ cul::Provider::Ptr p3{std::addressof(mp3), [](cul::Provider*){}};
692+
693+ std::set<cul::Provider::Ptr> providers{p1, p2, p3};
694+
695+ cul::FusionProvider fp{providers, std::make_shared<cul::NewerOrMoreAccurateUpdateSelector>()};
696+
697+ NiceMock<MockEventConsumer> mec;
698+ EXPECT_CALL(mec, on_new_position(_)).Times(1);
699+ EXPECT_CALL(mec, on_new_velocity(_)).Times(1);
700+ EXPECT_CALL(mec, on_new_heading(_)).Times(1);
701+
702+ fp.updates().position.connect([&mec](const cul::Update<cul::Position>& p){mec.on_new_position(p);});
703+ fp.updates().heading.connect([&mec](const cul::Update<cul::Heading>& h){mec.on_new_heading(h);});
704+ fp.updates().velocity.connect([&mec](const cul::Update<cul::Velocity>& v){mec.on_new_velocity(v);});
705+
706+ mp1.inject_update(cul::Update<cul::Position>());
707+ mp2.inject_update(cul::Update<cul::Heading>());
708+ mp3.inject_update(cul::Update<cul::Velocity>());
709+}
710+
711+#include <com/ubuntu/location/clock.h>
712+
713+TEST(FusionProvider, more_timely_update_is_chosen)
714+{
715+ using namespace ::testing;
716+
717+ NiceMock<MockProvider> mp1, mp2;
718+
719+ cul::Provider::Ptr p1{std::addressof(mp1), [](cul::Provider*){}};
720+ cul::Provider::Ptr p2{std::addressof(mp2), [](cul::Provider*){}};
721+
722+ std::set<cul::Provider::Ptr> providers{p1, p2};
723+
724+ cul::FusionProvider fp{providers, std::make_shared<cul::NewerOrMoreAccurateUpdateSelector>()};
725+
726+ cul::Update<cul::Position> before, after;
727+ before.when = cul::Clock::now() - std::chrono::seconds(12);
728+ before.value = cul::Position(cul::wgs84::Latitude(), cul::wgs84::Longitude(), cul::wgs84::Altitude(), cul::Position::Accuracy::Horizontal{50*cul::units::Meters});
729+ after.when = cul::Clock::now();
730+ after.value = cul::Position(cul::wgs84::Latitude(), cul::wgs84::Longitude(), cul::wgs84::Altitude(), cul::Position::Accuracy::Horizontal{500*cul::units::Meters});
731+
732+ NiceMock<MockEventConsumer> mec;
733+ EXPECT_CALL(mec, on_new_position(before)).Times(1);
734+ EXPECT_CALL(mec, on_new_position(after)).Times(1);
735+
736+ fp.updates().position.connect([&mec](const cul::Update<cul::Position>& p){mec.on_new_position(p);});
737+
738+ mp1.inject_update(before);
739+ mp2.inject_update(after);
740+
741+}
742+
743+TEST(FusionProvider, more_accurate_update_is_chosen)
744+{
745+ using namespace ::testing;
746+
747+ NiceMock<MockProvider> mp1, mp2;
748+
749+ cul::Provider::Ptr p1{std::addressof(mp1), [](cul::Provider*){}};
750+ cul::Provider::Ptr p2{std::addressof(mp2), [](cul::Provider*){}};
751+
752+ std::set<cul::Provider::Ptr> providers{p1, p2};
753+
754+ cul::FusionProvider fp{providers, std::make_shared<cul::NewerOrMoreAccurateUpdateSelector>()};
755+
756+ cul::Update<cul::Position> before, after;
757+ before.when = cul::Clock::now() - std::chrono::seconds(5);
758+ before.value = cul::Position(cul::wgs84::Latitude(), cul::wgs84::Longitude(), cul::wgs84::Altitude(), cul::Position::Accuracy::Horizontal{50*cul::units::Meters});
759+ after.when = cul::Clock::now();
760+ after.value = cul::Position(cul::wgs84::Latitude(), cul::wgs84::Longitude(), cul::wgs84::Altitude(), cul::Position::Accuracy::Horizontal{500*cul::units::Meters});
761+
762+ NiceMock<MockEventConsumer> mec;
763+ // We should see the "older" position in two events
764+ EXPECT_CALL(mec, on_new_position(before)).Times(2);
765+
766+ fp.updates().position.connect([&mec](const cul::Update<cul::Position>& p){mec.on_new_position(p);});
767+
768+ mp1.inject_update(before);
769+ mp2.inject_update(after);
770+
771+}

Subscribers

People subscribed via source and target branches