Skip to content

Rich Information For User Position

Rich information for user position

This tutorial shows how to handle rich user position information.

Get started

Rich user position information requires the alert component to be enabled at the creation of a drive session. A drive session created with the alert component enabled will have rich user position information turned off by default. Rich user position information is detected along the most possible path (MPP) in free mode; in navigation mode, it follows the route.

1
2
3
4
5
6
// enable alert component
tn::drive::DriveSessionOptions options;
options.enable_alert = true;

const auto driveSession = tn::drive::api::DriveSessionFactory::createDriveSession(
    options, system, settings, mapContent, directionService);

Turn it on if rich user position information is needed. Once turned on, you will receive rich user position information including closest street, intersections, house number and shield icon.

// turn on rich user position information
driveSession->enableUserPositionDetection(true);

User position listener

Make a customized alert listener to handle user position updates.

class AlertObserver : public tn::drive::api::AlertEventListener
{
public:
    void onUserPositionInfoUpdated(const tn::drive::models::v1::UserPositionInfo& userPosition) override
    {
        // vehicle is off road if closest street information is available
        // NOTICE: closest street information not available does not mean vehicle is on road
        if (userPosition.closest_street_info.has_value())
        {
            const auto closetStreetName = parseRoadName(userPosition.closest_street_info->name);

            // the shortest crow fly distance from current vehicle location to the closest street
            const auto distanceToVehicle = userPosition.closest_street_info->distance_to_vehicle;

            const auto& admin = userPosition.closest_street_info->admin;
        }

        // vehicle is on road if current street name is available
        // NOTICE: current street name not available does not mean vehicle is off road
        if (userPosition.current_street_name.has_value())
        {
            const auto currentStreetName = parseRoadName(userPosition.current_street_name.value());
        }

        if (userPosition.time_zone.has_value())
        {
            const auto utcOffset = userPosition.time_zone->UTC_offset;
            const auto dstOffset = userPosition.time_zone->DST_offset;
            // calculate local time for user position according to UTC and DST offset
        }

        if (userPosition.shield_info.has_value())
        {
            const auto icon = driveSession->renderIcon(60, 48, userPosition.shield_info->shield_icon_context);
        }

        // ahead intersection when vehicle is on road
        if (userPosition.next_intersection.has_value())
        {
            // current road type and subtype may be different between road ahead and behind current vehicle location
            const auto currentRoadType = userPosition.next_intersection->current_road_summary.road_type;
            const auto currentRoadSubType = userPosition.next_intersection->current_road_summary.road_subtype;

            const auto crossRoadNames = pickCrossRoadNames(userPosition.next_intersection->cross_road_summaries);

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

        // behind intersection when vehicle is on road
        if (userPosition.previous_intersection.has_value())
        {
            // ...
        }
    }

    // omit other methods
};

// summaries will be sorted in place, so pass by value
std::vector<std::string> pickCrossRoadNames(std::vector<tn::drive::models::v1::RoadSummary> summaries)
{
    auto fSorter = [](const tn::drive::models::v1::RoadSummary& a, const tn::drive::models::v1::RoadSummary& b)
    {
        // road types with smaller values are with higher road classes
        return (static_cast<uint32_t>(a.road_type) < static_cast<uint32_t>(b.road_type));
    };

    std::sort(summaries.begin(), summaries.end(), fSorter);

    std::vector<std::string> names;
    uint32_t count = 0;
    for (const auto& summary : summaries)
    {
        const auto name = parseRoadName(summary.name);
        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 drive session.

const auto listener = tn::make_shared<AlertObserver>();
driveSession->addAlertEventListener(listener);

Unregister it when not needed.

driveSession->removeAlertEventListener(listener);

Customize user position detection distance

User position detection distance can be configured to adjust performance.

const std::string userPositionSettings = R"json(
{
    // Following configuration shows the default values for user position detection
    "UserPosition": 
    {
        //  Max ahead intersection detect distance, unit: meter.
        //  Note that if this value is larger than actual forward detect route length,
        //  it will not incur extra road detection.
        "AheadIntersectionDetectDistance": 30000,

        //  Max previous intersection detect distance, unit: meter.
        //  Note that if this value is larger than actual backward detect route length,
        //  it will not incur extra road detection.
        "PreviousIntersectionDetectDistance": 5000,

        //  The min distance for detecting UserPositinInfo in streaming mode, unit: meter.
        //  If the streaming data within this distance is not ready, will report the data failure to MapContent.
        "MinDemandDistanceForStreaming": 1000
    }
}
)json";

const auto settings = tn::foundation::Settings::Builder()
    .setString(tn::drive::api::SettingConstants::SETTING_ALERT_JSON_CONTENT, userPositionSettings)
    .build();

// enable alert component at the creation of a drive session to make customized user position settings effective
tn::drive::DriveSessionOptions options;
options.enable_alert = true;

const auto driveSession = tn::drive::api::DriveSessionFactory::createDriveSession(
    options, system, settings, mapContent, directionService);