Get started with positioning
The Positioning module enables your application to obtain and utilize location data, serving as the foundation for features like navigation, tracking, and location-based services. This data can be sourced either from the device's GPS or from a custom data source, offering flexibility to suit diverse application needs.
Using the Positioning module, you can:
- Leverage real GPS data: Obtain highly accurate, real-time location updates directly from the device's built-in GPS sensor.
- Integrate custom location data: Configure the module to use location data provided by external sources, such as mock services or specialized hardware.
In the following sections, you will learn how to grant the necessary location permissions for your app, set up live data sources, and manage location updates effectively. Additionally, we will explore how to customize the position tracker to align with your application's design and functionality requirements. This comprehensive guide will help you integrate robust and flexible positioning capabilities into your app.
Receive location updates
To receive updates about changes in the current position, we can register a listener implementation in PositionService using the addListener method with the desired sense::EDataType for example sense::EDataType::Position or sense::EDataType::ImprovedPosition. The given listener will be called continuously as new updates about current position are made.
Consult the Positions guide for more information about the IPosition class and the differences between raw positions and map matched position.
Raw positions
To listen for raw position updates (as they are pushed to the data source or received via the sensors), the following code can be used:
class MyPositionListenerImpl : public IPositionListener
{
public:
void onNewPosition( sense::PositionPtr pos ) override
{
// process new position
}
};
auto myPositionListenerPtr = gem::StrongPointerFactory<MyPositionListenerImpl>();
PositionService().addListener( myPositionListenerPtr, sense::EDataType::Position );
Map matched positions
Code similar to the one above, with the change that the sense::EDataType is now ImprovedPosition.
class MyPositionListenerImpl : public IPositionListener
{
public:
void onNewPosition( sense::PositionPtr position ) override
{
// process new position
auto improvedPosition = position->cast<sense::IImprovedPosition>();
// Current coordinates
Coordinates coordinates = improvedPosition->getCoordinates();
GEM_INFO_LOG( "New position: Lat=%f, Lon=%f", coordinates.getLatitude(), coordinates.getLongitude() );
// Speed in m/s (-1 if not available)
double speed = improvedPosition->getSpeed();
// Speed limit in m/s on the current road (0 if not available)
double speedLimit = improvedPosition->getRoadSpeedLimit();
// Heading angle in degrees (N=0, E=90, S=180, W=270, -1 if not available)
double course = improvedPosition->getCourse();
// Information about current road (if it is in a tunnel, bridge, ramp, one way, etc.)
auto roadModifiers = improvedPosition->getRoadModifier();
// Quality of the current position
auto fixQuality = improvedPosition->getFixQuality();
// Horizontal and vertical accuracy in meters
double accuracyHorizontal = improvedPosition->getHorizontalAccuracy();
double accuracyVertical = improvedPosition->getVerticalAccuracy();
}
};
auto myPositionListenerPtr = gem::StrongPointerFactory<MyPositionListenerImpl>();
PositionService().addListener( myPositionListenerPtr, sense::EDataType::ImprovedPosition );
During simulation, the positions provided through the given listener implementation correspond to the simulated locations generated as part of the navigation simulation process.
Get current location
To retrieve the current location, we can use the getPosition getter from the PositionService class. This method returns a PositionPtr object containing the latest location information or empty if no position data is available. This method is useful for accessing the most recent position data without registering for continuous updates.
auto currentPosition = PositionService().getPosition( sense::EDataType::Position );
if(currentPosition && currentPosition->isValid())
GEM_INFO_LOG( "Current position is valid" );
else
GEM_INFO_LOG( "Current position is NOT valid" );
The same getter can be used for map-matched positions by asking for ImprovedPosition and then casting the given object to sense::IImprovedPosition.