Skip to content

备选路

支持范围: 目前仅在乘用车(非 EV)Cloud 模式下支持此功能。

功能介绍

导航过程中,SDK 可持续检测与当前导航路线不同的备选路线(alternative routes),供 HMI 在地图上并列展示,用户对比后主动切换。备选路不一定更优(与 更优的路 区分)。

检测由 SDK 调度(按道路类型周期重试、路线变化后内部重试)。HMI 不要自行定时调用请求接口。

核心接口:

接口 说明
NavigationServiceOptions.Builder.setAlternativeRouteOptions(...) 创建 NavigationService 时配置默认检测策略
NavigationSession.enableAlternativeRouteDetection(enable) 导航中开启或关闭持续检测
NavigationEventListener.onAlternativeRoutesUpdated(info) 备选路列表或状态更新
NavigationSession.acceptAlternativeRoute(route) 用户选择某条备选路并切换

用户接受备选路后,换路进度由 换路通知 的 onNavigationRouteUpdating 通知(reason 常为 ALTERNATIVE_ROUTE_SELECTED)。同时可能收到 onAlternativeRoutesUpdated(NAVIGATION_ROUTE_CHANGED)。

前置条件: 已 startNavigation 并持有 NavigationSession;已注册 NavigationEventListener。

流程概览

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
创建 NavigationService 时配置 AlternativeRouteOptions(可选)
   ↓
startNavigation
   ↓
enableDetection=true 则自动开启;否则导航中调用 enableAlternativeRouteDetection(true)
   ↓
onAlternativeRoutesUpdated(AlternativeRouteUpdateInfo)
   ↓
reason == ALTERNATIVE_ROUTES_DETECTED → 展示 navigationRoute + alternativeRoutes
   ↓
用户选择 → acceptAlternativeRoute(alternativeRoute)
   ↓
onNavigationRouteUpdating + onAlternativeRoutesUpdated(NAVIGATION_ROUTE_CHANGED)
   ↓
更新导航路线上下文与地图(见「换路通知」)

配置:AlternativeRouteOptions

在创建 NavigationService 时设置。每个新导航 session 继承该配置作为初始检测行为。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
val navigationService = NavigationService.Factory.createInstance(
    NavigationServiceOptions.Builder()
        .setAlternativeRouteOptions(
            AlternativeRouteOptions.Builder()
                .enableDetection(true)                 // 导航开始后自动开启持续检测,默认 false
                .setMaxRouteNumber(1)                  // 每次最多保留条数,1 或 2,默认 1
                .setMaxTimeToBifurcation(600)          // 至分岔点最大时间(秒),默认 600
                .setLocalRoadDetectionInterval(120)    // 普通路无结果重试间隔(秒),默认 120
                .setHighwayDetectionInterval(360)      // 高速无结果重试间隔(秒),默认 360
                .setEtaDeltaThreshold(null)            // ETA 过滤阈值(秒),默认 null = 不过滤
                .build()
        )
        .build()
)

未配置时:检测默认关闭;其它参数使用上表默认值。

AlternativeRouteOptions.Builder 参数

方法 说明 默认 有效范围
enableDetection(Boolean) 新 session 是否自动开启持续检测 false —
setMaxRouteNumber(Int) 每次计算最多保留的备选路条数 1 [1, 2]
setMaxTimeToBifurcation(Int) 至分岔点最大预计时间(秒),超出则过滤 600 [0, 3600]
setLocalRoadDetectionInterval(Int) 普通路无结果后的下次检测间隔(秒) 120 [30, 3600]
setHighwayDetectionInterval(Int) 高速无结果后的下次检测间隔(秒) 360 [30, 3600]
setEtaDeltaThreshold(Int?) 允许的 etaDelta 上限(秒);null 不做 ETA 过滤 null [-3600, 3600] 或 null

超出有效范围的值会被忽略,不生效。

etaDelta 与 etaDeltaThreshold

etaDelta = 备选路 ETA − 当前导航路 ETA(秒)。正数表示备选更慢,负数表示备选更快。

过滤规则:保留 etaDelta <= etaDeltaThreshold 的备选路。

配置 含义
null 不按 ETA 过滤(默认)
0 只保留更快或相等(etaDelta <= 0)
15 最多允许慢 15 秒
-60 至少快 60 秒

导航中开关:enableAlternativeRouteDetection

1
2
navigationSession.enableAlternativeRouteDetection(true)   // 开启持续检测
navigationSession.enableAlternativeRouteDetection(false)  // 关闭并取消已调度的重试
  • 返回 true 表示已接受;false 表示 session 已不可用。
  • 若创建 Service 时已 enableDetection(true),导航开始后无需再调开启。
  • 关闭后不再回调检测结果,也不再自动重试。

已废弃: requestAlternativeRoutesCalculation 不再执行计算,仅打 warning log。请改用 enableAlternativeRouteDetection(true),并在 startNavigation 前通过 setAlternativeRouteOptions 配置参数。

接收更新:onAlternativeRoutesUpdated

1
fun onAlternativeRoutesUpdated(info: AlternativeRouteUpdateInfo)

NavigationEventListener 中该回调带默认空实现,需按需 override。

触发时机

开启持续检测后,以下情况会触发本回调:

  1. 至少一条路满足备选路条件,可供展示
  2. 未找到满足条件的备选路(无候选、被过滤、功能不可用、计算出错等)
  3. 导航路线发生变化且此前已有备选 candidate(例如用户接受备选路、偏航后换路);无 candidate 时不回调
  4. 已进入备选路的分岔点已过

SDK 负责调度下次检测,HMI 不要为 NO_ALTERNATIVE_ROUTES 自行实现定时器再请求。

AlternativeRouteUpdateInfo.Reason

常量 说明 HMI 建议
ALTERNATIVE_ROUTES_DETECTED 至少一条可用备选路(alternativeRoutes 非空) 展示 alternativeRoutes,绘制备选路线样式
NO_ALTERNATIVE_ROUTES 无有效备选路(含计算失败、离线不可用等) 隐藏备选路;SDK 会按道路类型间隔重试
NAVIGATION_ROUTE_CHANGED 导航路已更新,且更新前存在备选 candidate 刷新列表;列表为空时 SDK 内部约 5 秒后重试
PASSED 备选路入口点已过 移除失效备选路;列表为空时 SDK 内部约 5 秒后重试

以下枚举仅兼容保留,SDK 不会再发出:

常量 说明
CALCULATION_SUCCESS 已废弃,等价于 ALTERNATIVE_ROUTES_DETECTED
CALCULATION_FAILURE 已废弃,失败场景统一为 NO_ALTERNATIVE_ROUTES

AlternativeRouteUpdateInfo 字段

字段 说明
reason 本次更新原因(先读)
navigationRoute 当前正在导航的路线
alternativeRoutes 当前可用的备选路列表;接受某条备选路后,原导航路可能出现在此列表中

AlternativeRoute 字段

字段 说明
route 备选路线(Route)
bifurcationTime 沿当前导航路至分岔点的预计时间(秒)
bifurcationDistance 沿当前导航路至分岔点的距离(米)
distanceDelta 与当前导航路的里程差(米)
etaDelta 备选路 ETA − 当前导航路 ETA(秒);正=更慢,负=更快
firstEdgeIndex 备选路第一个 edge 的 RouteEdgeIndex;地图绘制备选路时可传入 RouteRenderOptions.firstAlternativeRouteEdge

切换备选路:acceptAlternativeRoute

1
val success = navigationSession.acceptAlternativeRoute(alternativeRoute)
  • 接受后,该备选路成为新的导航路线,原导航路线会作为备选路之一保留在后续 alternativeRoutes 中。
  • 返回 true 表示成功;false 表示备选路已失效(例如分岔点已过、列表已更新)。
  • 成功后关注 onNavigationRouteUpdating 与 onAlternativeRoutesUpdated(NAVIGATION_ROUTE_CHANGED)更新 UI。

示例代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
val navigationService = NavigationService.Factory.createInstance(
    NavigationServiceOptions.Builder()
        .setAlternativeRouteOptions(
            AlternativeRouteOptions.Builder()
                .enableDetection(true)
                .setMaxRouteNumber(1)
                .setMaxTimeToBifurcation(600)
                .setLocalRoadDetectionInterval(120)
                .setHighwayDetectionInterval(360)
                .setEtaDeltaThreshold(null)
                .build()
        )
        .build()
)

// 若未配置 enableDetection(true),导航开始后可手动开启:
// navigationSession.enableAlternativeRouteDetection(true)

override fun onAlternativeRoutesUpdated(info: AlternativeRouteUpdateInfo) {
    when (info.reason) {
        AlternativeRouteUpdateInfo.Reason.ALTERNATIVE_ROUTES_DETECTED -> {
            mainHandler.post {
                drawNavigationRoute(info.navigationRoute)
                info.alternativeRoutes.forEach { alt ->
                    mapView.routesController().add(
                        listOf(alt.route),
                        listOf(
                            RouteRenderOptions(
                                alternativeRoute = true,
                                firstAlternativeRouteEdge = alt.firstEdgeIndex
                            )
                        )
                    )
                }
            }
        }
        AlternativeRouteUpdateInfo.Reason.PASSED,
        AlternativeRouteUpdateInfo.Reason.NAVIGATION_ROUTE_CHANGED -> {
            mainHandler.post { refreshAlternativeRoutesOnMap(info) }
        }
        AlternativeRouteUpdateInfo.Reason.NO_ALTERNATIVE_ROUTES -> {
            mainHandler.post { hideAlternativeRoutesOnMap() }
            // 不要自行定时重试,SDK 会按配置间隔再次检测
        }
        else -> {}
    }
}

fun onAlternativeRouteSelected(alt: AlternativeRoute) {
    if (navigationSession?.acceptAlternativeRoute(alt) == true) {
        // 换路结果见 onNavigationRouteUpdating
    }
}

注意事项

  • 与更优的路区分: 备选路是平行路线选择,不强调「更优」;更优路见 更优的路(onBetterRouteDetected + acceptRouteProposal)。
  • 不要自行定时请求: 无结果重试、路线变化后的重试由 SDK 完成。检出备选路后(ALTERNATIVE_ROUTES_DETECTED)不会立刻周期重试。
  • NAVIGATION_ROUTE_CHANGED 不会在无 candidate 时发出: 导航刚启动、或从未检出备选时的 reroute,不会用该 reason 刷新列表。
  • acceptAlternativeRoute 可能失败: 分岔点已过或列表已变化时返回 false,应刷新 onAlternativeRoutesUpdated 最新数据后再选。
  • 地图样式: 当前导航路与备选路应使用不同样式;绘制备选路时使用 firstEdgeIndex 标明从何处与主路分离。备选路线型与颜色由 TSS 单独定义,使用前请先配置。
  • 回调线程: Message 线程,更新 UI / MapView 请切主线程。
  • 仅 Cloud: 离线 / onboard 场景会回调 NO_ALTERNATIVE_ROUTES。