From b09c040bab1042e47a1a499c42161241fb8f7688 Mon Sep 17 00:00:00 2001 From: vng Date: Sun, 5 Oct 2014 19:13:01 +0300 Subject: [PATCH] Cross-platform logic of choosing bearing between GPS and Compass, according to the current use case. --- .../maps/DownloadResourcesActivity.java | 5 -- .../src/com/mapswithme/maps/MWMActivity.java | 14 ---- .../com/mapswithme/maps/SearchActivity.java | 5 -- .../maps/bookmarks/BookmarkListAdapter.java | 5 -- .../maps/location/LocationService.java | 35 +--------- base/timer.cpp | 7 +- base/timer.hpp | 2 +- iphone/Maps/Platform/LocationManager.mm | 27 ++------ map/framework.cpp | 7 +- map/location_state.cpp | 64 +++++++++++++------ map/location_state.hpp | 7 ++ platform/location.hpp | 2 +- 12 files changed, 69 insertions(+), 111 deletions(-) diff --git a/android/src/com/mapswithme/maps/DownloadResourcesActivity.java b/android/src/com/mapswithme/maps/DownloadResourcesActivity.java index 987fc7a6f8..dc7701e74e 100644 --- a/android/src/com/mapswithme/maps/DownloadResourcesActivity.java +++ b/android/src/com/mapswithme/maps/DownloadResourcesActivity.java @@ -593,11 +593,6 @@ public class DownloadResourcesActivity extends MapsWithMeBaseFragmentActivity { } - @Override - public void onDrivingHeadingUpdated(long time, double heading) - { - } - @Override public void onLocationError(int errorCode) { diff --git a/android/src/com/mapswithme/maps/MWMActivity.java b/android/src/com/mapswithme/maps/MWMActivity.java index 1171d5529e..7083303e3b 100644 --- a/android/src/com/mapswithme/maps/MWMActivity.java +++ b/android/src/com/mapswithme/maps/MWMActivity.java @@ -995,20 +995,6 @@ public class MWMActivity extends NvEventQueueActivity mInfoView.updateAzimuth(north); } - @SuppressWarnings("deprecation") - @Override - public void onDrivingHeadingUpdated(long time, double heading) - { - double arr[] = new double[]{heading}; - LocationUtils.correctCompassAngles(getWindowManager().getDefaultDisplay().getOrientation(), arr); - heading = arr[0]; - - nativeCompassUpdated(time, heading, heading, 0.0); - - if (mInfoView.getState() != State.HIDDEN) - mInfoView.updateAzimuth(heading); - } - /// Callback from native location GUI element processing. public void onLocationStateModeChangedCallback(final int newMode) { diff --git a/android/src/com/mapswithme/maps/SearchActivity.java b/android/src/com/mapswithme/maps/SearchActivity.java index 685a2ba8a3..c0b866dd48 100644 --- a/android/src/com/mapswithme/maps/SearchActivity.java +++ b/android/src/com/mapswithme/maps/SearchActivity.java @@ -762,11 +762,6 @@ public class SearchActivity extends MapsWithMeBaseListActivity implements Locati { } - @Override - public void onDrivingHeadingUpdated(long time, double heading) - { - } - @Override public void onLocationError(int errorCode) { diff --git a/android/src/com/mapswithme/maps/bookmarks/BookmarkListAdapter.java b/android/src/com/mapswithme/maps/bookmarks/BookmarkListAdapter.java index 0125141743..a79ce95b7e 100644 --- a/android/src/com/mapswithme/maps/bookmarks/BookmarkListAdapter.java +++ b/android/src/com/mapswithme/maps/bookmarks/BookmarkListAdapter.java @@ -156,11 +156,6 @@ public class BookmarkListAdapter extends BaseAdapter // We don't show any arrows for bookmarks any more. } - @Override - public void onDrivingHeadingUpdated(long time, double heading) - { - } - @Override public void onLocationError(int errorCode) { diff --git a/android/src/com/mapswithme/maps/location/LocationService.java b/android/src/com/mapswithme/maps/location/LocationService.java index 09729c8b3d..09641997c5 100644 --- a/android/src/com/mapswithme/maps/location/LocationService.java +++ b/android/src/com/mapswithme/maps/location/LocationService.java @@ -41,7 +41,6 @@ public enum LocationService implements private static final double DEFAULT_SPEED_MPS = 5; private static final float DISTANCE_TO_RECREATE_MAGNETIC_FIELD_M = 1000; - private static final float MIN_SPEED_CALC_DIRECTION_MPS = 1; private static final String GS_LOCATION_PROVIDER = "fused"; /// These constants should correspond to values defined in platform/location.hpp @@ -56,8 +55,6 @@ public enum LocationService implements public void onCompassUpdated(long time, double magneticNorth, double trueNorth, double accuracy); - public void onDrivingHeadingUpdated(long time, double heading); - public void onLocationError(int errorCode); } @@ -65,8 +62,6 @@ public enum LocationService implements private Location mLastLocation = null; private long mLastLocationTime; - /// Current heading if we are moving (-1.0 otherwise) - private double mDrivingHeading = -1.0; private boolean mIsGPSOff; private WifiLocationScanner mWifiScanner = null; @@ -152,13 +147,6 @@ public enum LocationService implements it.next().onCompassUpdated(time, magneticNorth, trueNorth, accuracy); } - private void notifyDrivingHeadingUpdated(long time, double heading) - { - final Iterator it = mListeners.iterator(); - while (it.hasNext()) - it.next().onDrivingHeadingUpdated(time, heading); - } - public void startUpdate(LocationListener listener) { mListeners.add(listener); @@ -204,14 +192,6 @@ public enum LocationService implements } } - private void updateDrivingHeading(Location l) - { - if (l.getSpeed() >= MIN_SPEED_CALC_DIRECTION_MPS && l.hasBearing()) - mDrivingHeading = LocationUtils.bearingToHeading(l.getBearing()); - else - mDrivingHeading = -1.0; - } - private void emitLocation(Location l) { mLastLocation = l; @@ -228,8 +208,6 @@ public enum LocationService implements if (mLocationProvider.isLocationBetterThanCurrent(l)) { - updateDrivingHeading(l); - if (mSensorManager != null) { // Recreate magneticField if location has changed significantly @@ -245,14 +223,6 @@ public enum LocationService implements } } - private void emitCompassResults(long time, double north, double trueNorth, double offset) - { - if (mDrivingHeading >= 0.0) - notifyDrivingHeadingUpdated(time, mDrivingHeading); - else - notifyCompassUpdated(time, north, trueNorth, offset); - } - @Override public void onSensorChanged(SensorEvent event) { @@ -284,7 +254,7 @@ public enum LocationService implements if (mMagneticField == null) { // -1.0 - as default parameters - emitCompassResults(event.timestamp, magneticHeading, -1.0, -1.0); + notifyCompassUpdated(event.timestamp, magneticHeading, -1.0, -1.0); } else { @@ -292,7 +262,7 @@ public enum LocationService implements final double offset = Math.toRadians(mMagneticField.getDeclination()); final double trueHeading = LocationUtils.correctAngle(magneticHeading, offset); - emitCompassResults(event.timestamp, magneticHeading, trueHeading, offset); + notifyCompassUpdated(event.timestamp, magneticHeading, trueHeading, offset); } } } @@ -354,7 +324,6 @@ public enum LocationService implements // Reset current parameters to force initialize in the next startUpdate mMagneticField = null; - mDrivingHeading = -1.0; mIsActive = false; } diff --git a/base/timer.cpp b/base/timer.cpp index 538c833d10..0c9f58b0c5 100644 --- a/base/timer.cpp +++ b/base/timer.cpp @@ -11,9 +11,12 @@ namespace my { -Timer::Timer() +Timer::Timer(bool start/* = true*/) { - Reset(); + if (start) + Reset(); + else + m_startTime = 0.0; } double Timer::LocalTime() diff --git a/base/timer.hpp b/base/timer.hpp index 6521d4fed0..b465ec7294 100644 --- a/base/timer.hpp +++ b/base/timer.hpp @@ -14,7 +14,7 @@ class Timer double m_startTime; public: - Timer(); + explicit Timer(bool start = true); /// @return current UTC time in seconds, elapsed from 1970. static double LocalTime(); diff --git a/iphone/Maps/Platform/LocationManager.mm b/iphone/Maps/Platform/LocationManager.mm index d21b422388..2aea1ffa1e 100644 --- a/iphone/Maps/Platform/LocationManager.mm +++ b/iphone/Maps/Platform/LocationManager.mm @@ -24,7 +24,7 @@ m_isStarted = NO; m_observers = [[NSMutableSet alloc] init]; m_lastLocationTime = nil; - m_isCourse = NO; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(orientationChanged) name:UIDeviceOrientationDidChangeNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(batteryStateChangedNotification:) name:UIDeviceBatteryStateDidChangeNotification object:nil]; } @@ -157,16 +157,9 @@ - (void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)heading { - // Stop passing driving course if last time stamp for GPS location is later than 20 seconds. - if (m_lastLocationTime == nil || ([m_lastLocationTime timeIntervalSinceNow] < -20.0)) - m_isCourse = NO; - - if (!m_isCourse) - { - location::CompassInfo info; - [self heading:heading toCompassInfo:info]; - [self notifyCompassUpdate:info]; - } + location::CompassInfo info; + [self heading:heading toCompassInfo:info]; + [self notifyCompassUpdate:info]; } - (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation @@ -194,18 +187,6 @@ [self location:newLocation toGpsInfo:newInfo]; for (id observer in m_observers) [observer onLocationUpdate:newInfo]; - - // Pass current course if we are moving and GPS course is valid. - if (newLocation.speed >= 1.0 && newLocation.course >= 0.0) - { - m_isCourse = YES; - - location::CompassInfo info; - info.m_bearing = my::DegToRad(newLocation.course); - [self notifyCompassUpdate:info]; - } - else - m_isCourse = NO; } - (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error diff --git a/map/framework.cpp b/map/framework.cpp index 857ca6e3f2..607b170c2f 100644 --- a/map/framework.cpp +++ b/map/framework.cpp @@ -128,8 +128,7 @@ void Framework::OnLocationUpdate(GpsInfo const & info) { // pass compass value (for devices without compass) CompassInfo compass; - compass.m_magneticHeading = compass.m_trueHeading = 0.0; - compass.m_timestamp = rInfo.m_timestamp; + m_fixedPos.GetNorth(compass.m_bearing); OnCompassUpdate(compass); } @@ -150,7 +149,7 @@ void Framework::OnCompassUpdate(CompassInfo const & info) { #ifdef FIXED_LOCATION CompassInfo rInfo(info); - m_fixedPos.GetNorth(rInfo.m_trueHeading); + m_fixedPos.GetNorth(rInfo.m_bearing); #else CompassInfo const & rInfo = info; #endif @@ -160,7 +159,7 @@ void Framework::OnCompassUpdate(CompassInfo const & info) void Framework::StopLocationFollow() { - m_informationDisplay.locationState()->StopLocationFollow(); + GetLocationState()->StopLocationFollow(); } InformationDisplay & Framework::GetInformationDisplay() diff --git a/map/location_state.cpp b/map/location_state.cpp index 0e714d4aeb..0a5a1b17ad 100644 --- a/map/location_state.cpp +++ b/map/location_state.cpp @@ -16,12 +16,12 @@ #include "../indexer/mercator.hpp" -#include "../platform/platform.hpp" #include "../platform/location.hpp" #include "../geometry/rect2d.hpp" #include "../geometry/transformations.hpp" + namespace location { @@ -31,6 +31,7 @@ namespace static const int POSITION_Y_OFFSET = 120; static const double POSITION_TOLERANCE = 1.0E-6; // much less than coordinates coding error static const double ANGLE_TOLERANCE = my::DegToRad(3.0); +static const double GPS_BEARING_LIFETIME_S = 5.0; uint16_t IncludeModeBit(uint16_t mode, uint16_t bit) @@ -200,6 +201,7 @@ State::State(Params const & p) m_errorRadius(0), m_position(0, 0), m_drawDirection(0.0), + m_lastGPSBearing(false), m_afterPendingMode(Follow), m_currentSlotID(0) { @@ -277,12 +279,13 @@ void State::SwitchToNextMode() void State::RouteBuilded() { - ASSERT(GetPlatform().HasRouting(), ()); StopAllAnimations(); SetModeInfo(IncludeModeBit(m_modeInfo, RoutingSessionBit)); - if (GetMode() > NotFollow) + + Mode const mode = GetMode(); + if (mode > NotFollow) SetModeInfo(ChangeMode(m_modeInfo, NotFollow)); - else if (GetMode() == UnknownPosition) + else if (mode == UnknownPosition) { m_afterPendingMode = NotFollow; SetModeInfo(ChangeMode(m_modeInfo, PendingPosition)); @@ -291,9 +294,9 @@ void State::RouteBuilded() void State::StartRouteFollow() { - ASSERT(TestModeBit(m_modeInfo, RoutingSessionBit), ()); - ASSERT(GetPlatform().HasRouting(), ()); + ASSERT(IsInRouting(), ()); ASSERT(IsModeHasPosition(), ()); + m2::PointD const size(m_errorRadius, m_errorRadius); m_framework->ShowRectExVisibleScale(m2::RectD(m_position - size, m_position + size), scales::GetUpperComfortScale()); @@ -316,12 +319,7 @@ void State::TurnOff() void State::OnLocationUpdate(location::GpsInfo const & info) { - m2::RectD rect = MercatorBounds::MetresToXY(info.m_longitude, - info.m_latitude, - info.m_horizontalAccuracy); - - m_position = rect.Center(); - m_errorRadius = rect.SizeX() / 2; + Assign(info); setIsVisible(true); @@ -336,12 +334,11 @@ void State::OnLocationUpdate(location::GpsInfo const & info) void State::OnCompassUpdate(location::CompassInfo const & info) { - SetModeInfo(IncludeModeBit(m_modeInfo, KnownDirectionBit)); - - m_drawDirection = info.m_bearing; - - AnimateFollow(); - invalidate(); + if (Assign(info)) + { + AnimateFollow(); + invalidate(); + } } void State::CallStateModeListeners() @@ -804,4 +801,35 @@ void State::AnimateFollow() } } +void State::Assign(location::GpsInfo const & info) +{ + m2::RectD rect = MercatorBounds::MetresToXY(info.m_longitude, + info.m_latitude, + info.m_horizontalAccuracy); + m_position = rect.Center(); + m_errorRadius = rect.SizeX() / 2; + + if (info.HasBearing() && info.HasSpeed() && info.m_speed > 1.0) + { + SetDirection(my::DegToRad(info.m_bearing)); + m_lastGPSBearing.Reset(); + } +} + +bool State::Assign(location::CompassInfo const & info) +{ + if ((IsInRouting() && GetMode() >= Follow) || + (m_lastGPSBearing.ElapsedSeconds() < GPS_BEARING_LIFETIME_S)) + return false; + + SetDirection(info.m_bearing); + return true; +} + +void State::SetDirection(double bearing) +{ + m_drawDirection = bearing; + SetModeInfo(IncludeModeBit(m_modeInfo, KnownDirectionBit)); +} + } diff --git a/map/location_state.hpp b/map/location_state.hpp index 772a85fd47..c57f75d653 100644 --- a/map/location_state.hpp +++ b/map/location_state.hpp @@ -4,6 +4,8 @@ #include "../geometry/point2d.hpp" +#include "../base/timer.hpp" + #include "../std/function.hpp" #include "../std/shared_ptr.hpp" #include "../std/unique_ptr.hpp" @@ -135,6 +137,10 @@ namespace location ScreenBase const & GetModelView() const; + void Assign(location::GpsInfo const & info); + bool Assign(location::CompassInfo const & info); + void SetDirection(double bearing); + private: // Mode bits // { @@ -151,6 +157,7 @@ namespace location double m_errorRadius; //< error radius in mercator m2::PointD m_position; //< position in mercator double m_drawDirection; + my::Timer m_lastGPSBearing; Mode m_afterPendingMode; typedef map TModeListeners; diff --git a/platform/location.hpp b/platform/location.hpp index 36a751b833..7dc7eb6851 100644 --- a/platform/location.hpp +++ b/platform/location.hpp @@ -47,7 +47,7 @@ namespace location double m_speed; //!< metres per second //bool HasAltitude() const { return m_verticalAccuracy >= 0.0; } - //bool HasBearing() const { return m_bearing >= 0.0; } + bool HasBearing() const { return m_bearing >= 0.0; } bool HasSpeed() const { return m_speed >= 0.0; } };