02 – Positioning

The basics: Indoor and Outdoor positioning #

Indoor and/or outdoor positioning is where everybody should start. Start by executing the Basic Java Android or Basic Swift iOS examples and copy & paste the following code in your “MainActivity” or “ViewController”.

public class MainActivity extends AppCompatActivity {
    private static final String TAG = MainActivity.class.getSimpleName();

    //First, declare a LocationListener. This will receive the computed geolocations, status changes and errors
    private LocationListener locationListener = new LocationListener() {

        @Override
        public void onLocationChanged(Location location) {
            Log.i(TAG, "onLocationChanged() called with: location = [" + location + "]");
        }

        @Override
        public void onStatusChanged(@NonNull LocationStatus status) {
            Log.i(TAG, "onStatusChanged() called with: status = [" + status + "]");
        }

        @Override
        public void onError(@NonNull Error error) {
            Log.e(TAG, "onError() called with: error = [" + error + "]");
        }
    };


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        //Initialize Situm SDK
        SitumSdk.init(this);

        //Ask for runtime permissions (ACCESS_FINE_LOCATION)
        ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION},0);

        //Build the LocationRequest with default parameters
        LocationRequest locationRequest = new LocationRequest.Builder().build();

        //Start positioning! -> Geolocations will be passed to the locationListener callbacks
        SitumSdk.locationManager().requestLocationUpdates(locationRequest, locationListener);

    }
}

class ViewController: UIViewController, SITLocationDelegate {

    var sitLocManager: SITLocationManager = SITLocationManager.sharedInstance()

...

    //This method is called when the user clicks the "Initialization Button"
    @IBAction func initializeButton(_ sender: UIButton) {

        //This function has been defined in the "Grant app permissions" Section
        requestLocationAuth()

        //Set the delegate so the update functions receive the messages
        sitLocManager.delegate = self
    }

    //This method is called when the user clicks the "StartButton"
    @IBAction func startRequestButton(_ sender: UIButton) {    

        //Create the request to activate positioning
        let request: SITLocationRequest = SITLocationRequest()

        //Start positioning by requesting location updates
        sharedLocManager.requestLocationUpdates(request)
    }

...

//    Delegate functions to receive notifications
    func locationManager(_ locationManager: SITLocationInterface, didUpdate location: SITLocation) {
        print("*POSITION UPDATED*\nPosition was updated to:\n Latitude: \(location.position.coordinate().latitude)\n Longitude:  (location.position.coordinate().longitude).")
    }
    
    func locationManager(_ locationManager: SITLocationInterface, didFailWithError error: Error?) {
        print("*POSITIO UPDATED*\nThere was an error with the request: \(error?.localizedDescription ?? "")")
    }
    
    func locationManager(_ locationManager: SITLocationInterface, didUpdate state: SITLocationState) {
        print("*POSITION UPDATED*\nState was updated to \(state.rawValue)")
    }

As you can see, a few entities work together in order to compute the smartphone geolocation.

EntityExplanationDocumentation
LocationManagerHandles all positioning tasks. Implements methods “requestLocationUpdates” and “removeUpdates”, which start & stop positioning.Android
iOS
LocationRequestAllows to configure the positioning parameters: Building vs Global, whether or not to use WiFi or BLE, etc.  Android
iOS
LocationListenerInterface allows you to receive and respond to all the generated geolocations, as well as to other useful information (status and errors).Android
iOS

Running the code #

If you build & execute the previous code, your application will produce a log similar to the following one (for the Android example, iOS will be similar).  

Initialization

2021-02-06 00:49:14.441 2592-2592/com.example.androidtestapp I/MainActivity: onStatusChanged() called with: status = [CALCULATING]

2021-02-06 00:49:15.535 2592-2592/com.example.androidtestapp I/MainActivity: onStatusChanged() called with: status = [STARTING]

At first, the onStatusChanged method is called to inform that the Situm SDK is in status “CALCULATING”. Then, it is called again to inform that is is in status “STARTING”. 

After a few moments, the positioning will start producing a few first outdoor geolocations.  If you open the RealTime Panel, you should see your geolocation on the world!

Outdoor positioning

If you inspect the log lines, you will see very interesting information.

2021-02-06 00:49:16.567 2592-2592/com.example.androidtestapp I/MainActivity: onLocationChanged() called with: location = [Location{provider='SITUM_PROVIDER', deviceId=356655406358, timestamp=1612568956544, position=Point{buildingIdentifier='-1', floorIdentifier='-1', cartesianCoordinate=CartesianCoordinate{x=0,00, y=0,00}, coordinate=Coordinate{latitude=43,356441, longitude=-8,413430}, isOutdoor=true}, quality=HIGH, accuracy=20.287, cartesianBearing=Angle{radians=0.00, degrees=0.00}, bearing=Angle{radians=0.51, degrees=29.44}, bearingQuality=HIGH, customFields={}}]

Let’s examine this line in detail:

  1. The location provider is SITUM_PROVIDER. This is just an internal parameter.
  2. The deviceId is the identifier of the device that is running the application.
  3. The timestamp is the current Unix Timestamp, in milliseconds since Jan 01 1970 (UTC).
  4. Position is an object that represents the smartphone location. In this case:
    1. buildingIdentifier and floorIdentifier are equals to “-1”. This means that the user is not within a known building or floor, therefore the location is an outdoor location.
    2. cartesianCoordinate should be the cartesian location within a building’s floorplan, but since we are dealing with an outdoor location, it is equals to {x=0.00, y=0.00} (default value).  
    3. coordinate is equals to {latitude=43.356441, longitude=-8.413430}. This are the location coordinates in WSG 84 format.
    4. isOutdoor=true. Again, this indicates that we are dealing with an outdoor location.
  5. Although quality is HIGH, you should not pay attention to this: this parameter refers to the quality of indoor locations, and as we have seen, this is an outdoor location.
  6. Accuracy is 20.287. This is the approximate error radius within which the smartphone location is. When producing outdoor locations (like this one), this number is provided by the smartphone GPS provider.
  7. cartesianBearing should be the cartesian orientation with respect to the bulding’s axis, but since we are dealing with an outdoor location, it is equals to {radians=0.00, degrees=0.00}.
  8. bearing is the orientation with respect to the Earth North. In this case, it is equals to {radians=0.51, degrees=29.44}.
  9. Although bearingQuality is HIGH, you should not pay attention to this: this parameter refers to the quality of the cartesianBearing, and as we have seen, this value is not available since we are dealing with an outdoor location.
  10. customFields is JSON dictionary that may contain key-value tuples. It is empty in this case. 

Behind the scenes, Situm will try to detect if you are within a building that has been configured with Situm technology. If you are in one and open the RealTime Panel, you will see your indoor geolocation within the building.

 Again, you may inspect the log lines.

2021-02-06 01:14:47.319 2592-2592/com.example.androidtestapp I/MainActivity: onLocationChanged() called with: location = [Location{provider='SITUM_PROVIDER', deviceId=356655406358, timestamp=1612570486718, position=Point{buildingIdentifier='6541', floorIdentifier='13483', cartesianCoordinate=CartesianCoordinate{x=17,50, y=10,20}, coordinate=Coordinate{latitude=43,356433, longitude=-8,413040}, isOutdoor=false}, quality=HIGH, accuracy=0.70591295, cartesianBearing=Angle{radians=1.66, degrees=95.19}, bearing=Angle{radians=6.19, degrees=354.81}, bearingQuality=HIGH, customFields={}}]

You may notice that:

  1. Position is now an indoor geolocation:
    1. buildingIdentifier is assigned to “6541”, which corresponds to the building identifier where the user is. 
    2. floorIdentifier is assigned to “13483”, which corresponds to the floor identifier where the user is.
    3. cartesianCoordinate now specifies the specific 2D location of the user within the building in cartesian coordinates. coordinate specifies that same location, but converted to the WSG84 latitude-longitude.
    4. isOutdoor now indicates that the user is not outdoors.
  2. Quality is HIGH. Now you may take it into account, since it represents the indoor location quality (and we are dealing with an indoor location).
  3. Accuracy is 0.70591295. This is the approximate error radius within which the smartphone location is. When producing indoor locations (like this one), this number is computed by Situm system.  
  4. cartesianBearing is {radians=1.66, degrees=95.19}, representing the cartesian orientation with respect to the bulding’s axis.
  5. bearing is the orientation with respect to the Earth North. In this case, it is equals to {radians=6.19, degrees=354.81}.
  6. bearingQuality is HIGH. Now you may take it into account, since it represents the cartesianBearing quality (and we are dealing with an indoor location).

That’s it! You have developed an application that is able to track your indoor & outdoor smartphone’s location, anywhere in the world.

Geolocation modes #

Situm is able to provide Indoor Positions within any building where Situm technology has been configured. Situm provides three methods (mutually exclusive) for computing this indoor geolocation: Situm Indoor, Calibrated Indoor GPS, Uncalibrated Indoor GPS

Indoor geolocation modeDescriptionHow to use it
Situm IndoorDetermines the user’s position in the calibrated areas of a building by matching WiFi/BLE signals received with the calibrations. More info.Set to false LocationRequest.Builder().useGps (Android) or SITLocationRequest.useGPS (iOS)
Calibrated Indoor GPSMixes the WiFi/BLE + the GPS signals within all the calibrated areas. Recommended in buildings with indoor/outdoor areas with good GPS coverage.  More info.Set to true LocationRequest.Builder().useGps (Android) or SITLocationRequest.useGPS (iOS)
Uncalibrated Indoor GPSWorks just as the Calibrated GPS Indoor mode, but can also use the GPS signal within outdoor uncalibrated areas of your building. This can help you avoid the effort of calibrating big outdoor areas while still having the benefits of using the GPS signal in them. Set to true LocationRequest.Builder().useGps (Android) or SITLocationRequest.useGPS (iOS).

Create geofences with a specific configuration in all the outdoor areas where you want Situm to use the GPS information.

In any of these methods, there may be times when Situm will not be able to provide a valid Indoor Location, usually because the signals do not match with what is expected in a given building. In this case, Situm will inform that the user is not in any known building.

You may try each of these modes using our Situm Mapping Tool application: this will help you get a better understanding on how they work and what you can expect from them.

Building vs Global Mode #

Situm SDK allows you to choose between two positioning modes: Building and Global Mode.

ModeBuilding detectorDescriptionHow to use it
BuildingNoneLocates the user within a specific building. If user is in the building, generates Indoor Positions. Otherwise, informs that the user is not in the building. Set the  LocationRequest.Builder().buildingIdentifier (Android) or SITLocationRequest.buildingID (iOS).
GlobalDetects automatically the building where the user is and provides his Indoor Position.
GPS basedDefault detector but unrecommended. User will be geolocated in the nearest building from those within a certain maximum distance. More info.Set the OutdoorLocationOptions.Builder()
.buildingDetector
to GPS_PROXIMITY (Android) or SITOutdoorLocationOptions.buildingDetector to kSITGpsProximity (iOS).
WiFi/BLE basedRecommended. The user user will be geolocated inside the building whose calibration signals match better with those perceived by the user smartphone. More info.

For fast building transitions, enable the “Always on mode” (Android only). More info.
In Android, set the OutdoorLocationOptions.Builder()
.buildingDetector
to WIFI, BLE or WIFI_AND_BLE, depending on the sensor you want to use to match the signals. In iOS, set the SITOutdoorLocationOptions.buildingDetector to kSITBLE.

Always on Mode (Android only). Set the OutdoorLocationOptions.Builder().scansBasedDetectorAlwaysOn method to true.
GPS + WiFi/BLE basedOnly available when using the Uncalibrated GPS Indoor positioning mode.  User will be geolocated inside the building where: 1) calibration signals match better with those perceived by the user smartphone, and/or 2) GPS signal falls within one of the GPS-configured geofences of the building. In Android, set the OutdoorLocationOptions.Builder()
.buildingDetector
to WIFI, BLE or WIFI_AND_BLE, depending on the sensor you want to use to match the signals. Also, set to true LocationRequest.Builder().useGps and the OutdoorLocationOptions.Builder.useGeofencesInBuildingSelector.

In iOS, set the SITOutdoorLocationOptions.buildingDetector to kSITBLE and set to true SITLocationRequest.useGPS and the SITOutdoorLocationOptions.useGeofencesInBuildingSelector.

This mode also requires to configure especial geofences in the building.

This mode supports the Always on Mode, like the WiFi/BLE mode (Android only). Set the OutdoorLocationOptions.Builder().scansBasedDetectorAlwaysOn method to true.

Note that the OutdoorLocationOptions / SITOutdoorLocationOptions are passed to the LocationRequest.Builder.outdoorLocationOptions (Android) or SITLocationRequest.outdoorLocationOptions (iOS).

Indoor Positioning Sensor Management #

As explained in this article, in order to compute the most accurate geolocation, Situm can use many of the sensor information that modern smartphones provide.  Situm SDK allows you to activate/deactivate most of these sensors when computing indoor geolocations. This can come in handy to activate special features by enable a certain sensor, saving battery by disabling another, etc.

SensorSub-ModeDescriptionHow to use it
WiFi (Android only)Scan WiFi for indoor positioning and building detection.Enabled by default. Controlled by the  LocationRequest.Builder().useWifi (Android). Not available in iOS
Ignore WiFi throttling (Android only)In Android 10, you may ignore the WiFi Throttling limitation and scan WiFi at full speed. Also, in Android 11 with SitumSDK v2.69.1 and inferior.

Android 5,6,7,8 are not affected by WiFi Throttling. Android 9 doesn’t allow to disable WiFi Throttling. Android 11 + Situm SDK v>2.69.1 scans at full speed if WiFi Throttling is disabled. So, this parameter has no effect on them.

Set to true LocationRequets.Builder().ignoreWiFiThrottling to scan at full speed. False by default (assumes WiFi Throttling is enabled in the device).

Make sure you have turned off WiFi Throttling in your device before.
BLEScan BLE for indoor positioning and building detection.Enabled by default. Controlled by the  LocationRequest.Builder().useBLE (Android). Not available in iOS (always scans BLE).
Beacon filtersBy default, Situm only detects beacons with Situm’s UUID (73697475-6D73-6974-756D-736974756D15) and Kontakt’s UUID f7826da6-4fa2-4e98-8024-bc5b71e0893e). Nevertheless, you may use any other iBeacon with a different UUID. Recommended way is through Situm Dashboard: see Section “How do I configure my beacons?” of this article.


Alternatively, you may hardcode other beacons UUIDs in your app, using the method LocationRequest.Builder().addBeaconFilter or LocationRequest.Builder().addBeaconFilters (Android). In iOS, you may use SITLocationRequest.beaconFilters.
Auto-enable BLE (Android only)User may disable Bluetooth on the smartphone, preventing Situm SDK to scan BLE signals. SitumSDK re-enables Bluetooth automatically if LocationRequest.Builder().useBLE is true.To disable this automatis, set LocationRequest.Builder().autoEnableBleDuringPositioning to false.
GPSUse GPS for indoor positioning (useful in buildings with outdoor areas with good GPS coverage).

Using GPS implies that Calibrated or Uncalibrated GPS Indoor modes will be used. Do not mistake using GPS with Global Mode: GPS can be used both in Building and Global modes.
Disabled by default. Enable it by setting LocationRequest.Builder().useGPS to true.
GyroscopeGyroscope measures the angular velocity (rate at which the smartphone turns). Combined with compass, Situm provides an accurate orientation. Enabled by default. You may disable it (not recommended) by setting LocationRequest.Builder().useGyro to false. 
CompassCompass measures the absolute smartphone orientation with respect to the Earth’s North.Enabled by default. You may disable it (not recommended) by setting  LocationRequest.Builder().useCompass to false.
(1) User disables Bluetooth on Device Settings
(2) Device Bluetooth is Disabled

Detail on how Auto-enable BLE works

(3) Situm Re-Enables Bluetooth automatically

Location Updates Configuration #

By default, Situm SDK computes one geolocation estimate per second, uploads it to the Situm cloud, and gets stored.

This is fine for more apps, but sometimes you may want to tweak this behaviour (or even disable positioning at all). For example, in a wayfinding app the user may turn around in an instant. Waiting one second to show the turn (default behaviour) does not account for a good navigation UX: faster orientation updates will be handy.

Indoor Positioning #

ConfigurationDescriptionHow to use it
Location updates intervalInterval between consecutive Indoor Location updates (by default, 1 second) provided via the LocationListener.onLocationChanged callback.  More info.Set LocationRequest.Builder().interval (Android) or SITLocationRequest.interval (iOS) to the interval value in milliseconds.
Location updates displacementConfigures the minimum movement that the user has to perform to produce a new location via the LocationListener.onLocationChanged callback.  More info.Set LocationRequest.Builder().smallestDisplacement (Android) or SITLocationRequest.interval (iOS) to the smallest displacement (in meters) required.
Dead reckoning (faster orientation changes)Computes fast orientation changes between every two locations and provides several location updates per second (only orientation changes, approx 1 per 150ms) via the LocationListener.onLocationChanged callback.

Useful to provide a better user experience when the user turns quickly.
Deactivated by default. Recommended to enable it for a better UX in wayfinding apps.
To enable it, set the LocationRequest.Builder().useDeadReckoning (Android) or SITLocationRequest.useDeadReckoning (iOS) to true.

None of the above configurations change: 1) the frequency with which Situm computes it’s geolocations, 2) the frequency and number of geolocations that Situm uploads to Situm Cloud. 

Outdoor Positioning (Global Mode only) #

ConfigurationDescriptionHow to use it
Disable outdoor positioningYou may want to do this to make sure that users are not tracked outside of the building(s).

If you disable it, the GPS based building detector will not work. Therefore, you should set a different building detector (e.g. WiFi/BLE based).
Set to false OutdoorLocationOptions.Builder().enableOutdoorPositions (Android) or SITOutdoorLocationOptions.enableOutdoorPositions (iOS).
Compute intervalFrequency with which outdoor locations are computed. Helps reducing battery consumption.Set the OutdoorLocationOptions.Builder().computeInterval (Android) or SITOutdoorLocationOptions.computeInterval (iOS).
Update IntervalFrequency with which outdoor locations are delivered to the application. Does not change the frequency with which Situm computes geolocations (it just discards some of them).

Useful to reduce the amount of data stored in Situm Cloud to perform geospatial with less data.
Set the OutdoorLocationOptions.Builder().updateInterval (Android) or SITOutdoorLocationOptions.updateInterval (iOS).
Minimum outdoor accuracyFilters out outdoor positioning that do not meet a certain accuracy . Set OutdoorLocationOptions.Builder().minimumOutdoorLocationAccuracy (Android) or SITOutdoorLocationOptions.minimumOutdoorLocationAccuracy (iOS).

Subscribe to our newsletter

BASIC INFORMATION ON DATA PROTECTION

Data controller: SITUM TECHNOLOGIES, S.L.
Contact: Data controller: situm@situm.es
Responsible for protection: dpo@situm.es
Purpose and legal basis: To manage the sending of SITUM newsletters only with consent.
Legitimation: Express consent of the interested party.
Recipients: The data will not be passed on to third parties with the exception of legal obligations.
Retention period: As long as the interested party remains subscribed to the newsletter (a link to unsubscribe will be available in each newsletter sent by Situm).
Rights: The interested party may at any time revoke their consent, as well as exercise their rights of opposition, access, conservation, rectification, limitation, deletion of data and not be subject to a decision based only on automated data processing, by writing to SITUM at the addresses indicated.
Additional Information: You can consult additional and detailed information on Data Protection in our privacy policy.

Please, download your copy here

Thank you for downloading our whitepaper. Please do not hesitate to contact us if you would like to know more about how our solutions can help your business. Download whitepaper


Close window