Skip to content

Rich Information For User Position

Rich information for user position

This tutorial shows how to get rich user position information.

Get started

Rich user position information is detected along the most possible path (MPP). In user position information, you will get things including current road, nearby road, intersections, admin and timezone.

User position listener

Make a customized position listener to handle user position updates.

class PositionObserver : public tn::drive::api::PositionEventListener
{
public:
    void onPositionIndicatorUpdated(const tn::drive::models::v1::Indicator& indicator) override
    {
        // vehicle is on road if matched road is available
        if (indicator.matched_road.has_value())
        {
            const auto currentStreetName = parseRoadName(indicator.matched_road->road_name);

            const auto houseNumber = indicator.matched_road->house_number;

            // generate the shield icon via the context of current matched road
            if (indicator.shield_info.has_value())
            {
                const auto icon = navigationService->renderIcon(60, 48, indicator.shield_info->shield_icon_context);
            }
        }

        // vehicle is off road if the nearby road information is available
        // NOTICE: the nearby road information not available does not mean vehicle is on road
        if (indicator.nearby_road.has_value())
        {
            const auto nearbyRoadName = parseRoadName(indicator.nearby_road->name);

            // the crow fly distance from current vehicle location to the nearby road
            const auto distanceToVehicle = indicator.nearby_road->distance;
        }

        // regional info at the vehicle location
        if (indicator.regional.has_value())
        {
            const auto urban = indicator.regional->urban;

            const auto admin = indicator.regional->admin_info;

            const auto utcOffset = indicator.regional->time_zone.UTC_offset;
            const auto dstOffset = indicator.regional->time_zone.DST_offset;
            // calculate local time for user position according to UTC and DST offset
        }

        // ahead intersection when vehicle is on road
        if (indicator.ahead_intersection.has_value())
        {
            // location of the intersection
            const auto location = indicator.ahead_intersection->location;

            // road names of the cross roads
            const auto crossRoadNames = pickCrossRoadNames(indicator.ahead_intersection->cross_roads);

            // distance along the road from current vehicle location to intersection location
            const auto distanceToVehicle = indicator.ahead_intersection->distance;
        }

        // behind intersection when vehicle is on road
        if (indicator.behind_intersection.has_value())
        {
            // ...
        }
    }

    // omit other methods
};

std::vector<std::string> pickCrossRoadNames(const std::vector<tn::mapcontent::models::v1::NameString>& cross_roads)
{
    std::vector<std::string> names;
    uint32_t count = 0;
    for (const auto& cross_road : cross_roads)
    {
        const auto name = parseRoadName(cross_road);
        names.push_back(name);

        count++;
        if (count >= 2)
        {
            // pick two cross road names at most
            break;
        }        
    }

    return names;
}

Refer to parse name string for road names for parseRoadName implementation.

Register the listener after creation of navigation service.

const auto listener = tn::make_shared<PositionObserver>();
navigationService->addPositionEventListener(listener);

Unregister it when not needed.

navigationService->removePositionEventListener(listener);