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
=== added file 'include/location_service/com/ubuntu/location/fusion_provider.h'
--- include/location_service/com/ubuntu/location/fusion_provider.h 1970-01-01 00:00:00 +0000
+++ include/location_service/com/ubuntu/location/fusion_provider.h 2016-03-10 19:30:01 +0000
@@ -0,0 +1,59 @@
1/*
2 * Copyright © 2016 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License version 3,
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Scott Sweeny <scott.sweeny@canonical.com
17 */
18#ifndef LOCATION_SERVICE_COM_UBUNTU_LOCATION_FUSION_PROVIDER_H
19#define LOCATION_SERVICE_COM_UBUNTU_LOCATION_FUSION_PROVIDER_H
20
21#include <com/ubuntu/location/provider.h>
22#include <com/ubuntu/location/provider_selection_policy.h>
23#include <com/ubuntu/location/update_selector.h>
24
25namespace com
26{
27namespace ubuntu
28{
29namespace location
30{
31class FusionProvider : public Provider
32{
33public:
34 typedef std::shared_ptr<FusionProvider> Ptr;
35
36 FusionProvider(const std::set<Provider::Ptr>& providers, const UpdateSelector::Ptr& update_selector);
37
38 bool matches_criteria(const Criteria &criteria) override;
39 void on_wifi_and_cell_reporting_state_changed(location::WifiAndCellIdReportingState state) override;
40 void on_reference_location_updated(const Update<Position>& position) override;
41 void on_reference_velocity_updated(const Update<Velocity>& velocity) override;
42 void on_reference_heading_updated(const Update<Heading>& heading) override;
43 void start_position_updates() override;
44 void stop_position_updates() override;
45 void start_heading_updates() override;
46 void stop_heading_updates() override;
47 void start_velocity_updates() override;
48 void stop_velocity_updates() override;
49
50private:
51 Optional<Update<Position>> last_position;
52 std::set<Provider::Ptr> providers;
53 std::vector<core::ScopedConnection> connections;
54};
55}
56}
57}
58
59#endif // LOCATION_SERVICE_COM_UBUNTU_LOCATION_FUSION_PROVIDER_H
060
=== added file 'include/location_service/com/ubuntu/location/fusion_provider_selection_policy.h'
--- include/location_service/com/ubuntu/location/fusion_provider_selection_policy.h 1970-01-01 00:00:00 +0000
+++ include/location_service/com/ubuntu/location/fusion_provider_selection_policy.h 2016-03-10 19:30:01 +0000
@@ -0,0 +1,39 @@
1/*
2 * Copyright © 2016 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License version 3,
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Scott Sweeny <scott.sweeny@canonical.com
17 */
18#ifndef COM_UBUNTU_LOCATION_FUSION_PROVIDER_SELECTION_POLICY_H
19#define COM_UBUNTU_LOCATION_FUSION_PROVIDER_SELECTION_POILCY_H
20
21#include <com/ubuntu/location/provider_selection_policy.h>
22
23namespace com
24{
25namespace ubuntu
26{
27namespace location
28{
29// This policy selects all providers, supplying them in the form of a fusion
30// provider for higher quality position updates
31struct FusionProviderSelectionPolicy : public ProviderSelectionPolicy
32{
33 ProviderSelection determine_provider_selection_for_criteria(const Criteria &criteria, const ProviderEnumerator &enumerator);
34};
35}
36}
37}
38
39#endif // COM_UBUNTU_LOCATION_FUSION_PROVIDER_SELECTION_POILCY_H
040
=== added file 'include/location_service/com/ubuntu/location/newer_or_more_accurate_update_selector.h'
--- include/location_service/com/ubuntu/location/newer_or_more_accurate_update_selector.h 1970-01-01 00:00:00 +0000
+++ include/location_service/com/ubuntu/location/newer_or_more_accurate_update_selector.h 2016-03-10 19:30:01 +0000
@@ -0,0 +1,60 @@
1/*
2 * Copyright © 2016 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License version 3,
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Scott Sweeny <scott.sweeny@canonical.com
17 */
18#ifndef LOCATION_SERVICE_COM_UBUNTU_LOCATIONNEWER_OR_MORE_ACCURATE_UPDATE_SELECTOR_H
19#define LOCATION_SERVICE_COM_UBUNTU_LOCATIONNEWER_OR_MORE_ACCURATE_UPDATE_SELECTOR_H
20
21#include <com/ubuntu/location/update_selector.h>
22
23namespace com
24{
25namespace ubuntu
26{
27namespace location
28{
29class NewerOrMoreAccurateUpdateSelector : public UpdateSelector
30{
31public:
32 typedef std::shared_ptr<NewerOrMoreAccurateUpdateSelector> Ptr;
33
34 Update<Position> select(const Update<Position>& older,
35 const Update<Position>& newer) override
36 {
37 // Basically copied this value from the Android fusion provider
38 static const std::chrono::seconds cutoff(11);
39
40 // If the new position is newer by a significant margin then just use it
41 if (newer.when > older.when + cutoff) {
42 return newer;
43 }
44
45 // Choose the position with the smaller accuracy circle if both have them
46 if (!older.value.accuracy.horizontal)
47 return newer;
48 if (!newer.value.accuracy.horizontal)
49 return older;
50 if (newer.value.accuracy.horizontal < older.value.accuracy.horizontal)
51 return newer;
52 else
53 return older;
54 }
55};
56}
57}
58}
59#endif // LOCATION_SERVICE_COM_UBUNTU_LOCATIONNEWER_OR_MORE_ACCURATE_UPDATE_SELECTOR_H
60
061
=== added file 'include/location_service/com/ubuntu/location/newer_update_selector.h'
--- include/location_service/com/ubuntu/location/newer_update_selector.h 1970-01-01 00:00:00 +0000
+++ include/location_service/com/ubuntu/location/newer_update_selector.h 2016-03-10 19:30:01 +0000
@@ -0,0 +1,45 @@
1/*
2 * Copyright © 2016 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License version 3,
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Scott Sweeny <scott.sweeny@canonical.com
17 */
18#ifndef LOCATION_SERVICE_COM_UBUNTU_LOCATION_ALWAYS_SELECT_NEW_UPDATE_H
19#define LOCATION_SERVICE_COM_UBUNTU_LOCATION_ALWAYS_SELECT_NEW_UPDATE_H
20
21#include <com/ubuntu/location/update_selector.h>
22
23namespace com
24{
25namespace ubuntu
26{
27namespace location
28{
29class NewerUpdateSelector : public UpdateSelector
30{
31public:
32 typedef std::shared_ptr<NewerUpdateSelector> Ptr;
33
34 Update<Position> select (const Update<Position>& older,
35 const Update<Position>& newer) override
36 {
37 return newer;
38 }
39};
40}
41}
42}
43
44#endif // LOCATION_SERVICE_COM_UBUNTU_LOCATION_ALWAYS_SELECT_NEW_UPDATE_H
45
046
=== added file 'include/location_service/com/ubuntu/location/update_selector.h'
--- include/location_service/com/ubuntu/location/update_selector.h 1970-01-01 00:00:00 +0000
+++ include/location_service/com/ubuntu/location/update_selector.h 2016-03-10 19:30:01 +0000
@@ -0,0 +1,49 @@
1/*
2 * Copyright © 2016 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License version 3,
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Scott Sweeny <scott.sweeny@canonical.com
17 */
18#ifndef LOCATION_SERVICE_COM_UBUNTU_LOCATION_UPDATE_SELECTOR_H
19#define LOCATION_SERVICE_COM_UBUNTU_LOCATION_UPDATE_SELECTOR_H
20
21#include <com/ubuntu/location/update.h>
22#include <com/ubuntu/location/position.h>
23
24namespace com
25{
26namespace ubuntu
27{
28namespace location
29{
30class UpdateSelector
31{
32public:
33 typedef std::shared_ptr<UpdateSelector> Ptr;
34
35 UpdateSelector(const UpdateSelector&) = delete;
36 UpdateSelector& operator=(const UpdateSelector&) = delete;
37 virtual ~UpdateSelector() = default;
38
39 virtual Update<Position> select(const Update<Position>& older,
40 const Update<Position>& newer) = 0;
41
42protected:
43 UpdateSelector() = default;
44};
45}
46}
47}
48#endif // LOCATION_SERVICE_COM_UBUNTU_LOCATION_UPDATE_SELECTOR_H
49
050
=== modified file 'src/location_service/com/ubuntu/location/CMakeLists.txt'
--- src/location_service/com/ubuntu/location/CMakeLists.txt 2015-11-26 08:28:38 +0000
+++ src/location_service/com/ubuntu/location/CMakeLists.txt 2016-03-10 19:30:01 +0000
@@ -16,10 +16,12 @@
16 ${UBUNTU_LOCATION_SERVICE_PUBLIC_HEADERS}16 ${UBUNTU_LOCATION_SERVICE_PUBLIC_HEADERS}
1717
18 default_provider_selection_policy.cpp18 default_provider_selection_policy.cpp
19 fusion_provider_selection_policy.cpp
19 non_selecting_provider_selection_policy.cpp20 non_selecting_provider_selection_policy.cpp
2021
21 criteria.cpp22 criteria.cpp
22 engine.cpp23 engine.cpp
24 fusion_provider.cpp
23 init_and_shutdown.cpp25 init_and_shutdown.cpp
24 position.cpp26 position.cpp
25 provider.cpp27 provider.cpp
2628
=== added file 'src/location_service/com/ubuntu/location/fusion_provider.cpp'
--- src/location_service/com/ubuntu/location/fusion_provider.cpp 1970-01-01 00:00:00 +0000
+++ src/location_service/com/ubuntu/location/fusion_provider.cpp 2016-03-10 19:30:01 +0000
@@ -0,0 +1,141 @@
1/*
2 * Copyright © 2016 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License version 3,
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Scott Sweeny <scott.sweeny@canonical.com
17 */
18 #include <com/ubuntu/location/fusion_provider.h>
19 #include <com/ubuntu/location/logging.h>
20 #include <com/ubuntu/location/update.h>
21
22namespace cu = com::ubuntu;
23namespace cul = com::ubuntu::location;
24
25cul::Provider::Features all_features()
26{
27 return cul::Provider::Features::position |
28 cul::Provider::Features::heading |
29 cul::Provider::Features::velocity;
30}
31
32cul::Provider::Requirements all_requirements()
33{
34 return cul::Provider::Requirements::cell_network |
35 cul::Provider::Requirements::data_network |
36 cul::Provider::Requirements::monetary_spending |
37 cul::Provider::Requirements::satellites;
38}
39
40
41cul::FusionProvider::FusionProvider(const std::set<location::Provider::Ptr>& providers, const UpdateSelector::Ptr& update_selector)
42 : Provider{all_features(), all_requirements()},
43 providers{providers}
44{
45
46 for (auto provider : providers)
47 {
48 connections.push_back(provider->updates().position.connect(
49 [this, update_selector](const cul::Update<cul::Position>& u)
50 {
51 // if this is the first update, use it
52 if (!last_position) {
53 mutable_updates().position(*(last_position = u));
54 } else {
55 try {
56 mutable_updates().position(*(last_position = update_selector->select(*last_position, u)));
57 } catch (const std::exception& e) {
58 LOG(WARNING) << "Error while updating position";
59 }
60 }
61 }));
62 connections.push_back(provider->updates().heading.connect(
63 [this](const cul::Update<cul::Heading>& u)
64 {
65 mutable_updates().heading(u);
66 }));
67 connections.push_back(provider->updates().velocity.connect(
68 [this](const cul::Update<cul::Velocity>& u)
69 {
70 mutable_updates().velocity(u);
71 }));
72 }
73
74}
75
76// We always match :)
77bool cul::FusionProvider::matches_criteria(const cul::Criteria&)
78{
79 return true;
80}
81
82// We forward all events to the other providers.
83void cul::FusionProvider::on_wifi_and_cell_reporting_state_changed(cul::WifiAndCellIdReportingState state)
84{
85 for (auto provider : providers)
86 provider->on_wifi_and_cell_reporting_state_changed(state);
87}
88
89void cul::FusionProvider::on_reference_location_updated(const cul::Update<cul::Position>& position)
90{
91 for (auto provider : providers)
92 provider->on_reference_location_updated(position);
93}
94
95void cul::FusionProvider::on_reference_velocity_updated(const cul::Update<cul::Velocity>& velocity)
96{
97 for (auto provider : providers)
98 provider->on_reference_velocity_updated(velocity);
99}
100
101void cul::FusionProvider::on_reference_heading_updated(const cul::Update<cul::Heading>& heading)
102{
103 for (auto provider : providers)
104 provider->on_reference_heading_updated(heading);
105}
106
107void cul::FusionProvider::start_position_updates()
108{
109 for (auto provider : providers)
110 provider->state_controller()->start_position_updates();
111}
112
113void cul::FusionProvider::stop_position_updates()
114{
115 for (auto provider : providers)
116 provider->state_controller()->stop_position_updates();
117}
118
119void cul::FusionProvider::start_heading_updates()
120{
121 for (auto provider : providers)
122 provider->state_controller()->start_heading_updates();
123}
124
125void cul::FusionProvider::stop_heading_updates()
126{
127 for (auto provider : providers)
128 provider->state_controller()->stop_heading_updates();
129}
130
131void cul::FusionProvider::start_velocity_updates()
132{
133 for (auto provider : providers)
134 provider->state_controller()->start_velocity_updates();
135}
136
137void cul::FusionProvider::stop_velocity_updates()
138{
139 for (auto provider : providers)
140 provider->state_controller()->stop_velocity_updates();
141}
0142
=== added file 'src/location_service/com/ubuntu/location/fusion_provider_selection_policy.cpp'
--- src/location_service/com/ubuntu/location/fusion_provider_selection_policy.cpp 1970-01-01 00:00:00 +0000
+++ src/location_service/com/ubuntu/location/fusion_provider_selection_policy.cpp 2016-03-10 19:30:01 +0000
@@ -0,0 +1,26 @@
1#include <com/ubuntu/location/fusion_provider.h>
2#include <com/ubuntu/location/fusion_provider_selection_policy.h>
3#include <com/ubuntu/location/newer_or_more_accurate_update_selector.h>
4
5namespace location = com::ubuntu::location;
6
7location::ProviderSelection location::FusionProviderSelectionPolicy::determine_provider_selection_for_criteria(
8 const location::Criteria&,
9 const location::ProviderEnumerator& enumerator)
10{
11 // We put all providers in a set.
12 std::set<location::Provider::Ptr> bag;
13 enumerator.for_each_provider([&bag](const location::Provider::Ptr& provider)
14 {
15 bag.insert(provider);
16 });
17
18 auto fusion_providers = std::make_shared<location::FusionProvider>(bag, std::make_shared<location::NewerOrMoreAccurateUpdateSelector>());
19
20 return location::ProviderSelection
21 {
22 fusion_providers, // position
23 fusion_providers, // heading
24 fusion_providers, // velocity
25 };
26}
027
=== modified file 'src/location_service/com/ubuntu/location/non_selecting_provider_selection_policy.cpp'
--- src/location_service/com/ubuntu/location/non_selecting_provider_selection_policy.cpp 2015-11-18 09:40:10 +0000
+++ src/location_service/com/ubuntu/location/non_selecting_provider_selection_policy.cpp 2016-03-10 19:30:01 +0000
@@ -17,130 +17,13 @@
17 */17 */
1818
19#include <com/ubuntu/location/non_selecting_provider_selection_policy.h>19#include <com/ubuntu/location/non_selecting_provider_selection_policy.h>
20#include <com/ubuntu/location/fusion_provider.h>
21#include <com/ubuntu/location/newer_update_selector.h>
2022
21#include <set>23#include <set>
2224
23namespace location = com::ubuntu::location;25namespace location = com::ubuntu::location;
2426
25namespace
26{
27
28location::Provider::Features all_features()
29{
30 return location::Provider::Features::position |
31 location::Provider::Features::heading |
32 location::Provider::Features::velocity;
33}
34
35location::Provider::Requirements all_requirements()
36{
37 return location::Provider::Requirements::cell_network |
38 location::Provider::Requirements::data_network |
39 location::Provider::Requirements::monetary_spending |
40 location::Provider::Requirements::satellites;
41}
42
43// A simple helper that takes a set of existing providers
44// and maps calls to each of them.
45struct BagOfProviders : public location::Provider
46{
47 BagOfProviders(const std::set<location::Provider::Ptr>& providers)
48 : location::Provider{all_features(), all_requirements()},
49 providers{providers}
50 {
51 // We connect to all updates of each provider.
52 for (auto provider : BagOfProviders::providers)
53 {
54 connections.push_back(provider->updates().position.connect([this](const location::Update<location::Position>& update)
55 {
56 mutable_updates().position(update);
57 }));
58
59 connections.push_back(provider->updates().heading.connect([this](const location::Update<location::Heading>& update)
60 {
61 mutable_updates().heading(update);
62 }));
63
64 connections.push_back(provider->updates().velocity.connect([this](const location::Update<location::Velocity>& update)
65 {
66 mutable_updates().velocity(update);
67 }));
68 }
69
70 }
71
72 // We always match :)
73 bool matches_criteria(const location::Criteria&) override
74 {
75 return true;
76 }
77
78 // We forward all events to the other providers.
79 void on_wifi_and_cell_reporting_state_changed(location::WifiAndCellIdReportingState state) override
80 {
81 for (auto provider : providers)
82 provider->on_wifi_and_cell_reporting_state_changed(state);
83 }
84
85 void on_reference_location_updated(const location::Update<location::Position>& position) override
86 {
87 for (auto provider : providers)
88 provider->on_reference_location_updated(position);
89 }
90
91 void on_reference_velocity_updated(const location::Update<location::Velocity>& velocity) override
92 {
93 for (auto provider : providers)
94 provider->on_reference_velocity_updated(velocity);
95 }
96
97 void on_reference_heading_updated(const location::Update<location::Heading>& heading) override
98 {
99 for (auto provider : providers)
100 provider->on_reference_heading_updated(heading);
101 }
102
103 void start_position_updates() override
104 {
105 for (auto provider : providers)
106 provider->state_controller()->start_position_updates();
107 }
108
109 void stop_position_updates() override
110 {
111 for (auto provider : providers)
112 provider->state_controller()->stop_position_updates();
113 }
114
115 void start_heading_updates() override
116 {
117 for (auto provider : providers)
118 provider->state_controller()->start_heading_updates();
119 }
120
121 void stop_heading_updates() override
122 {
123 for (auto provider : providers)
124 provider->state_controller()->stop_heading_updates();
125 }
126
127 void start_velocity_updates() override
128 {
129 for (auto provider : providers)
130 provider->state_controller()->start_velocity_updates();
131 }
132
133 void stop_velocity_updates() override
134 {
135 for (auto provider : providers)
136 provider->state_controller()->stop_velocity_updates();
137 }
138
139 std::set<location::Provider::Ptr> providers;
140 std::vector<core::ScopedConnection> connections;
141};
142}
143
144location::ProviderSelection location::NonSelectingProviderSelectionPolicy::determine_provider_selection_for_criteria(27location::ProviderSelection location::NonSelectingProviderSelectionPolicy::determine_provider_selection_for_criteria(
145 const location::Criteria&,28 const location::Criteria&,
146 const location::ProviderEnumerator& enumerator)29 const location::ProviderEnumerator& enumerator)
@@ -152,7 +35,7 @@
152 bag.insert(provider);35 bag.insert(provider);
153 });36 });
15437
155 auto bag_of_providers = std::make_shared<BagOfProviders>(bag);38 auto bag_of_providers = std::make_shared<FusionProvider>(bag, std::make_shared<NewerUpdateSelector>());
15639
157 // Our bag of providers is responsible for delivering position/heading/velocity updates.40 // Our bag of providers is responsible for delivering position/heading/velocity updates.
158 return location::ProviderSelection41 return location::ProviderSelection
15942
=== modified file 'src/location_service/com/ubuntu/location/service/default_configuration.cpp'
--- src/location_service/com/ubuntu/location/service/default_configuration.cpp 2014-11-14 11:33:05 +0000
+++ src/location_service/com/ubuntu/location/service/default_configuration.cpp 2016-03-10 19:30:01 +0000
@@ -20,7 +20,7 @@
20#include <com/ubuntu/location/service/trust_store_permission_manager.h>20#include <com/ubuntu/location/service/trust_store_permission_manager.h>
2121
22#include <com/ubuntu/location/engine.h>22#include <com/ubuntu/location/engine.h>
23#include <com/ubuntu/location/non_selecting_provider_selection_policy.h>23#include <com/ubuntu/location/fusion_provider_selection_policy.h>
2424
25namespace cul = com::ubuntu::location;25namespace cul = com::ubuntu::location;
26namespace culs = com::ubuntu::location::service;26namespace culs = com::ubuntu::location::service;
@@ -39,7 +39,7 @@
3939
40cul::ProviderSelectionPolicy::Ptr culs::DefaultConfiguration::the_provider_selection_policy()40cul::ProviderSelectionPolicy::Ptr culs::DefaultConfiguration::the_provider_selection_policy()
41{41{
42 return std::make_shared<cul::NonSelectingProviderSelectionPolicy>();42 return std::make_shared<cul::FusionProviderSelectionPolicy>();
43}43}
4444
45std::set<cul::Provider::Ptr> culs::DefaultConfiguration::the_provider_set(45std::set<cul::Provider::Ptr> culs::DefaultConfiguration::the_provider_set(
4646
=== modified file 'tests/provider_test.cpp'
--- tests/provider_test.cpp 2015-01-21 20:04:56 +0000
+++ tests/provider_test.cpp 2016-03-10 19:30:01 +0000
@@ -284,3 +284,128 @@
284 mp2.inject_update(cul::Update<cul::Heading>());284 mp2.inject_update(cul::Update<cul::Heading>());
285 mp3.inject_update(cul::Update<cul::Velocity>());285 mp3.inject_update(cul::Update<cul::Velocity>());
286}286}
287
288#include <com/ubuntu/location/fusion_provider.h>
289#include <com/ubuntu/location/newer_or_more_accurate_update_selector.h>
290
291TEST(FusionProvider, start_and_stop_of_updates_propagates_to_correct_providers)
292{
293 using namespace ::testing;
294
295 NiceMock<MockProvider> mp1, mp2, mp3;
296 EXPECT_CALL(mp1, start_position_updates()).Times(Exactly(1));
297 EXPECT_CALL(mp1, stop_position_updates()).Times(Exactly(1));
298 EXPECT_CALL(mp2, start_heading_updates()).Times(Exactly(1));
299 EXPECT_CALL(mp2, stop_heading_updates()).Times(Exactly(1));
300 EXPECT_CALL(mp3, start_velocity_updates()).Times(Exactly(1));
301 EXPECT_CALL(mp3, stop_velocity_updates()).Times(Exactly(1));
302
303 cul::Provider::Ptr p1{std::addressof(mp1), [](cul::Provider*){}};
304 cul::Provider::Ptr p2{std::addressof(mp2), [](cul::Provider*){}};
305 cul::Provider::Ptr p3{std::addressof(mp3), [](cul::Provider*){}};
306
307 cul::ProviderSelection selection{p1, p2, p3};
308 std::set<cul::Provider::Ptr> providers{p1, p2, p3};
309
310 //cul::FusionProvider pp{selection};
311 cul::FusionProvider fp{providers, std::make_shared<cul::NewerOrMoreAccurateUpdateSelector>()};
312
313 fp.start_position_updates();
314 fp.stop_position_updates();
315
316 fp.start_heading_updates();
317 fp.stop_heading_updates();
318
319 fp.start_velocity_updates();
320 fp.stop_velocity_updates();
321}
322
323TEST(FusionProvider, update_signals_are_routed_from_correct_providers)
324{
325 using namespace ::testing;
326
327 NiceMock<MockProvider> mp1, mp2, mp3;
328
329 cul::Provider::Ptr p1{std::addressof(mp1), [](cul::Provider*){}};
330 cul::Provider::Ptr p2{std::addressof(mp2), [](cul::Provider*){}};
331 cul::Provider::Ptr p3{std::addressof(mp3), [](cul::Provider*){}};
332
333 std::set<cul::Provider::Ptr> providers{p1, p2, p3};
334
335 cul::FusionProvider fp{providers, std::make_shared<cul::NewerOrMoreAccurateUpdateSelector>()};
336
337 NiceMock<MockEventConsumer> mec;
338 EXPECT_CALL(mec, on_new_position(_)).Times(1);
339 EXPECT_CALL(mec, on_new_velocity(_)).Times(1);
340 EXPECT_CALL(mec, on_new_heading(_)).Times(1);
341
342 fp.updates().position.connect([&mec](const cul::Update<cul::Position>& p){mec.on_new_position(p);});
343 fp.updates().heading.connect([&mec](const cul::Update<cul::Heading>& h){mec.on_new_heading(h);});
344 fp.updates().velocity.connect([&mec](const cul::Update<cul::Velocity>& v){mec.on_new_velocity(v);});
345
346 mp1.inject_update(cul::Update<cul::Position>());
347 mp2.inject_update(cul::Update<cul::Heading>());
348 mp3.inject_update(cul::Update<cul::Velocity>());
349}
350
351#include <com/ubuntu/location/clock.h>
352
353TEST(FusionProvider, more_timely_update_is_chosen)
354{
355 using namespace ::testing;
356
357 NiceMock<MockProvider> mp1, mp2;
358
359 cul::Provider::Ptr p1{std::addressof(mp1), [](cul::Provider*){}};
360 cul::Provider::Ptr p2{std::addressof(mp2), [](cul::Provider*){}};
361
362 std::set<cul::Provider::Ptr> providers{p1, p2};
363
364 cul::FusionProvider fp{providers, std::make_shared<cul::NewerOrMoreAccurateUpdateSelector>()};
365
366 cul::Update<cul::Position> before, after;
367 before.when = cul::Clock::now() - std::chrono::seconds(12);
368 before.value = cul::Position(cul::wgs84::Latitude(), cul::wgs84::Longitude(), cul::wgs84::Altitude(), cul::Position::Accuracy::Horizontal{50*cul::units::Meters});
369 after.when = cul::Clock::now();
370 after.value = cul::Position(cul::wgs84::Latitude(), cul::wgs84::Longitude(), cul::wgs84::Altitude(), cul::Position::Accuracy::Horizontal{500*cul::units::Meters});
371
372 NiceMock<MockEventConsumer> mec;
373 EXPECT_CALL(mec, on_new_position(before)).Times(1);
374 EXPECT_CALL(mec, on_new_position(after)).Times(1);
375
376 fp.updates().position.connect([&mec](const cul::Update<cul::Position>& p){mec.on_new_position(p);});
377
378 mp1.inject_update(before);
379 mp2.inject_update(after);
380
381}
382
383TEST(FusionProvider, more_accurate_update_is_chosen)
384{
385 using namespace ::testing;
386
387 NiceMock<MockProvider> mp1, mp2;
388
389 cul::Provider::Ptr p1{std::addressof(mp1), [](cul::Provider*){}};
390 cul::Provider::Ptr p2{std::addressof(mp2), [](cul::Provider*){}};
391
392 std::set<cul::Provider::Ptr> providers{p1, p2};
393
394 cul::FusionProvider fp{providers, std::make_shared<cul::NewerOrMoreAccurateUpdateSelector>()};
395
396 cul::Update<cul::Position> before, after;
397 before.when = cul::Clock::now() - std::chrono::seconds(5);
398 before.value = cul::Position(cul::wgs84::Latitude(), cul::wgs84::Longitude(), cul::wgs84::Altitude(), cul::Position::Accuracy::Horizontal{50*cul::units::Meters});
399 after.when = cul::Clock::now();
400 after.value = cul::Position(cul::wgs84::Latitude(), cul::wgs84::Longitude(), cul::wgs84::Altitude(), cul::Position::Accuracy::Horizontal{500*cul::units::Meters});
401
402 NiceMock<MockEventConsumer> mec;
403 // We should see the "older" position in two events
404 EXPECT_CALL(mec, on_new_position(before)).Times(2);
405
406 fp.updates().position.connect([&mec](const cul::Update<cul::Position>& p){mec.on_new_position(p);});
407
408 mp1.inject_update(before);
409 mp2.inject_update(after);
410
411}

Subscribers

People subscribed via source and target branches