Position Engine
Position Engine
Notice: using position engine directly is a legacy way to leverage the ability of the TA SDK.
It's recommended to use drive session instead.
Refer to the guide of drive session for more information.
Overview
The main feature of position engine, is to locate a vehicle on a map using original GPS data. The map will show vehicle coordinates to assist other features such as navigation, audio guidance, ADAS, etc. The original GPS information includes latitude, longitude, system timestamp, bearing, speed, number of satellites accepted, location accuracy, cumulative distance, and altitude. At the same time, position engine can also obtain road information such as drive side, road ID, speed limit, road type, road name, one-way road, time zone, urban or suburban area, and administrative level.
The information in the map is based on different terminal devices, and the terminal devices are divided into 2 types as below:
1. embedded navigation system
2. mobile devices such as phones and tablets
User location
Setup a position engine to get user location from original GPS data to a map matched location.
| // system instance is created for sharing in the whole SDK
// settings instance is created if any default setting does not meet the requirements, see following sections in this guide.
// Could be nullptr if default values are good enough.
// map_content instance is created for sharing in the whole SDK
auto pe = tn::position_engine::PositionEngineFactory::createPositionEngine(system, settings, map_content);
// make a customized location observer to handle user location changes
auto listener = tn::make_shared<LocationObserver>();
pe->addListener(listener);
// start engine
pe->start();
|
Stop the engine when it's not needed anymore.
| // stop engine when not needed anymore
pe->stop();
// remove location observer
pe->removeListener(listener);
|
Make a customized location observer to handle location updates.
PositionEngineListener::OnUpdateMapMatchingStatus
method provides the best location that is snapped to the road network in free mode. In navigation mode, it will try to snap the location to the route in navigation. If no road or route is possible to be snapped, the raw location will be used.
| class LocationObserver : public tn::position_engine::PositionEngineListener
{
public:
void OnUpdateMapMatchingStatus(const tn::shared_ptr<tn::position_engine::PeIndicator>& indicator) override
{
// this function is called on position engine working thread
// DO NOT do any time consuming thing here
const auto mode = indicator->getMode();
// navigation mode
if (mode == tn::position_engine::PeMode::PE_NAVIGATION)
{
const auto& on_route_status = indicator->getOnRoute();
if (on_route_status.isVehicleOnTrack())
{
// handle vehicle location changes on route
}
else
{
const auto& on_road_status = indicator->getCurRoad();
if (on_road_status.isVehicleOnRoad())
{
// handle vehicle location deviation from route onto another road
}
else
{
// handle vehicle location off road
}
}
}
// free mode
else if (mode == tn::position_engine::PeMode::PE_FOLLOW_ME_MAP)
{
const auto& on_road_status = indicator->getCurRoad();
if (on_road_status.isVehicleOnRoad())
{
// handle vehicle location changes on road network
}
else
{
// handle vehicle location changes off road
}
}
}
};
|
Update original GPS location to position engine to get map matched location.
| // get the time point when system starts up
const auto start_point = std::chrone::steady_clock::now();
// update original GPS location
tn::position_engine::VehicleLocationInfo gps_location;
gps_location.elapsed_time = std::chrono::duration<uint32_t, std::milli>(std::chrono::steady_clock::now() - start_point);
gps_location.heading = getVehicleHeading();
gps_location.speed = getVehicleSpeed();
gps_location.coordinate = getVehicleGpsLocation();
pe->updatePosition(gps_location);
|
Simulated navigation
The position engine will simulate a user's request for direction and inform the simulated location of other services for testing.
Simulation navigation can be started from navigation session.
| class LocationObserver : public tn::position_engine::PositionEngineListener
{
public:
void OnUpdateMapMatchingStatus(const tn::shared_ptr<tn::position_engine::PeIndicator>& indicator) override
{
// this function is called on position engine working thread
// DO NOT do any time consuming thing here
const auto mode = indicator->getMode();
// simulated navigation mode
if (mode == tn::position_engine::PeMode::PE_SIMULATION)
{
const auto& on_route_status = indicator->getOnRoute();
// vehicle location is always on route in simulated navigation mode
assert(on_route_status.isVehicleOnTrack());
// handle vehicle location change on route
}
}
};
|
Tips: in simulated navigation mode, position engine does not take position update via PositionEngine::updatePosition
Map matching feedback for dead reckoning calibration
Position engine will also assist with other services, such as providing calibration position to dead reckoning (DR).
| class LocationObserver : public tn::position_engine::PositionEngineListener
{
public:
void OnUpdateMapMatchingStatus(const tn::shared_ptr<tn::position_engine::PeIndicator>& indicator) override
{
// this function is called on position engine working thread
// DO NOT do any time consuming thing here
const auto& feedback = indicator->getMapMatchingFeedbackInfo();
// handle map matching feedback to calibrate dead reckoning
}
};
|
Multiple-layer detection (MLD)
In the case of multiple-layered roads, such as elevated roads or multiple-layered urban roads, position engine can identify which layer of the road the car is on. To make MLD to work correctly, accumulated distance and altitude must be provided with a fine grained reference.
| // update original GPS location with accumulated distance and altitude
tn::position_engine::VehicleLocationInfo gps_location;
// omit other parameters
gps_location.cum_dist = getAccumulatedDistance();
gps_location.cum_alt = getAccumulatedAltitude();
pe->updatePosition(gps_location);
|
When there is no MLD or MLD fails to identify, it's possible to select another road candidate and make vehicle matched to it.
| // get all road candidates
std::vector<tn::shared_ptr<tn::position_engine::PeCurRoad>> candidates;
pe->getAllAroundCandidates(candidates);
// select a candidate other than the first one which is the map matched result
const auto& candidate = candidates[1];
pe->selectCandidate(candidate->id());
|
Vehicle bearing calibration
When position engine is used on a mobile device, the bearing may be inaccurate. To avoid the possible sudden change of the bearing, it's recommended to turn on bearing calibration.
| // turn on bearing calibration
const auto settings = tn::foundation::Settings::Builder()
.setString(tn::position_engine::SettingConstants::SETTING_HEADING_CALIBRATION, "true")
.build();
// create a position engine with bearing calibration enabled
auto pe = tn::position_engine::PositionEngineFactory::createPositionEngine(system, settings, map_content);
|
Self-propelling in tunnel
When the vehicle is passing through a tunnel and has lost signal (offline), position engine can make it self-propelled based on a location deduction model.
It's recommended to turn on this feature for a mobile device or an embedded device without dead reckoning.
| // turn on self-propelling
const auto settings = tn::foundation::Settings::Builder()
.setString(tn::position_engine::SettingConstants::SETTING_SELF_PROPELLING_UPON_WEAK_GPS, "true")
.build();
// create a position engine with self-propelling enabled
auto pe = tn::position_engine::PositionEngineFactory::createPositionEngine(system, settings, map_content);
|