Merge lp:~ssweeny/location-service/fusion-provider.15.04 into lp:location-service/15.04
- fusion-provider.15.04
- Merge into 15.04
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 |
Related bugs: |
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
- 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
Konrad Zapałowicz (kzapalowicz) wrote : | # |
Good stuff just two places where reference could be considered.
- 222. By Scott Sweeny
-
Pass UpdateSelectors and return Updates by reference
- 223. By Scott Sweeny
-
Remove a couple of debug statements
Thomas Voß (thomas-voss) wrote : | # |
Minor remaining niggles inline.
- 224. By Scott Sweeny
-
Small changes addressing review comments
Scott Sweeny (ssweeny) wrote : | # |
One of the changes doesn't seem to work, but the others are done.
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_
These two changes don't work for me. The tests freeze up with a "this->
- 225. By Scott Sweeny
-
Prettify the last_position update code
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
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 | +} |
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 AlwaysSelectNew Update : 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 SignificantlyNe werOrMoreAccura teSelector : 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.