Highway Information Detection
This tutorial shows how to handle highway information.
Get started
Highway information detection requires alert component to be enabled at the creation of a navigation service.
A navigation service created with alert component enabled will have highway information detection turned off by default.
Highway information is detected along the most possible path (MPP) in free mode, in navigation mode, it follows the route.
| // enable alert component
tn::drive::NavigationServiceOptions options;
options.enable_alert = true;
const auto navigationService = tn::drive::api::NavigationServiceFactory::createNavigationService(
options, system, settings, mapContent, directionService);
|
Turn it on if highway information detection is needed.
Once turned on, you will receive highway information including highway names, highway shields, highway exits and signposts on highways.
| // turn on highway information detection
navigationService->enableHighwayInfoDetection(true);
|
Make a customized alert listener to handle highway information updates.
| class AlertObserver : public tn::drive::api::AlertEventListener
{
public:
void onHighwayInfoUpdated(const tn::drive::models::v1::HighwayInfo& highwayInfo) override
{
const auto& aheadHighways = highwayInfo.highway_info_ahead;
for (const auto& highway : aheadHighways.exits)
{
// names of highway road
// highway road may have multiple names, pick what you need from them
const auto& highwayNames = highway.basic.highway_names;
const auto pickedNames = pickHighwayNames(highwayNames);
// render highway shield icon
if (highway.basic.shield_icon.has_value())
{
const auto icon = navigationService->renderIcon(60, 48, highway.basic.shield_icon->shield_icon_context);
}
// this is where the exit branch off from main road
const auto& exitBeginLocation = highway.basic.location;
// this is where the link edges of the exit ends
// NOTICE: it may not be the actual end location due to detection distance limitations
const auto& exitEndLocation = highway.exit_location;
// along road distance in meters from current vehicle location to exit begin location
const auto distanceToVehicle = highway.basic.distance_to_vehicle;
// exit number and exit names come from signpost information if there's a signpost available
// otherwise it be detected along the exit path until a road name is found
const auto& exitNumber = highway.exit_number;
const auto& exitNames = highway.exit_names;
const auto& signpost = highway.signpost;
if (signpost.has_value())
{
for (const auto& name : exitNames)
{
// check if name comes from branch or towards names
for (const auto& branchName : signpost->branch_names)
{
if (name.text == branchName.text)
{
// it's a branch name
// ...
break;
}
}
for (const auto& towardsName : signpost->toward_names)
{
if (name.text == branchName.text)
{
// it's a towards name
// ...
break;
}
}
}
}
if (highway.exit_icon_context.has_value())
{
const auto exitIcon = navigationService->renderIcon(60, 48, highway.exit_icon_context.value());
}
}
}
// omit other methods
};
std::vector<std::string> pickHighwayNames(const std::vector<tn::mapcontent::models::v1::NameString>& names)
{
std::string defaultRoadNumber;
std::string defaultRoadName;
std::vector<std::string> officialRoadNumbers;
std::vector<std::string> officialRoadNames;
std::vector<std::string> pickedNames;
for (const auto& name : names)
{
if (name.usage_type == tn::mapcontent::models::v1::NameString::UsageType::DefaultOfficial)
{
if (name.format == tn::mapcontent::models::v1::NameString::Format::RoadNumber)
{
defaultRoadNumber = name;
}
else if (name.format == tn::mapcontent::models::v1::NameString::Format::Name)
{
defaultRoadName = name;
}
}
else if (name.usage_type == tn::mapcontent::models::v1::NameString::UsageType::Official)
{
if (name.format == tn::mapcontent::models::v1::NameString::Format::RoadNumber)
{
officialRoadNumbers.push_back(name);
}
else if (name.format == tn::mapcontent::models::v1::NameString::Format::Name)
{
officialRoadNames.push_back(name);
}
}
}
// default official road number is the most preferred one
if (!defaultRoadNumber.empty())
{
pickedNames.push_back(defaultRoadNumber);
}
// followed by other official road numbers
if (!officialRoadNumber.empty())
{
pickedNames.insert(pickedNames.end(), officialRoadNumber.begin(), officialRoadNumber.end());
}
// followed by default official road name
if (!defaultRoadName.empty())
{
pickedNames.push_back(defaultRoadName);
}
// followed by other official road names
if (!officialRoadNames.empty())
{
pickedNames.insert(pickedNames.end(), officialRoadNames.begin(), officialRoadNames.end());
}
return pickedNames;
}
|
Register the listener after creation of navigation service.
| const auto listener = tn::make_shared<AlertObserver>();
navigationService->addAlertEventListener(listener);
|
Unregister it when not needed.
| navigationService->removeAlertEventListener(listener);
|
Highway information detection distance can be configured to adjust performance.
These detection distances are shared for detection of highway names, highway shields, highway exits and signposts on highways.
The detection distance should be less than
detection distance configured for road graph builder.
| const std::string highwayDetectionSettings = R"json(
{
// Following configuration shows the default values for the detection distances
"HighwayInfo":
{
// Ahead highway Info retrieve length, unit: meter.
// Note that if this value is larger than actual forward detect route length,
// it will not incur extra road detection.
"DetectDistance": 81000,
// Behind highway Info retrieve length, unit: meter.
// Note that if this value is larger than actual forward detect route length,
// it will not incur extra road detection.
"MaxBehindDetectDistance": 5000,
// Max detect highway info on ahead path.
// Decrease this value could save cpu time cost.
"MaxAheadInfoCount": 10,
// The min distance for detecting HighwayInfo in streaming mode, unit: meter.
// If the streaming data within this distance is not ready, will report the data failure to MapContent.
"MinDemandDistanceForStreaming": 5000
}
}
)json";
const auto settings = tn::foundation::Settings::Builder()
.setString(tn::drive::api::SettingConstants::SETTING_ALERT_JSON_CONTENT, highwayDetectionSettings)
.build();
// enable alert component at the creation of a navigation service to make customized highway detection settings effective
tn::drive::NavigationServiceOptions options;
options.enable_alert = true;
const auto navigationService = tn::drive::api::NavigationServiceFactory::createNavigationService(
options, system, settings, mapContent, directionService);
|