车辆的路线可以沿时间轴分解,如下所示(假设有 n 次访问):
  |            |            |          |       |  T[2], |        |      |
  | Transition |  Visit #0  |          |       |  V[2], |        |      |
  |     #0     |    aka     |   T[1]   |  V[1] |  ...   | V[n-1] | T[n] |
  |  aka T[0]  |    V[0]    |          |       | V[n-2],|        |      |
  |            |            |          |       | T[n-1] |        |      |
  ^            ^            ^          ^       ^        ^        ^      ^
vehicle    V[0].start   V[0].end     V[1].   V[1].    V[n].    V[n]. vehicle
 start     (arrival)   (departure)   start   end      start    end     end
请注意,我们对以下两个方面有所不同:
- “准时事件”,例如车辆开始和结束以及每次访问的开始和结束(也称为到达和离开)。它们会在指定的秒数发生。
- “时间间隔”,例如访问本身,以及访问之间的转换。虽然时间间隔有时的时长可能为零(即开始和结束时间相同),但它们的时长通常为正数。
不变量:
- 如果有 n 次访问,则会出现 n+1 次转换。
- 访问始终围绕在其之后的转换(索引相同)和之后的转换(索引 + 1)。
- 车辆启动后面总是跟着转换 #0。
- 车辆结束始终在过渡 #n 之前。
放大后,下面是在 Transition 和 Visit 期间会发生的情况:
---+-------------------------------------+-----------------------------+-->
   |           TRANSITION[i]             |           VISIT[i]          |
   |                                     |                             |
   |  * TRAVEL: the vehicle moves from   |      PERFORM the visit:     |
   |    VISIT[i-1].departure_location to |                             |
   |    VISIT[i].arrival_location, which |  * Spend some time:         |
   |    takes a given travel duration    |    the "visit duration".    |
   |    and distance                     |                             |
   |                                     |  * Load or unload           |
   |  * BREAKS: the driver may have      |    some quantities from the |
   |    breaks (e.g. lunch break).       |    vehicle: the "demand".   |
   |                                     |                             |
   |  * WAIT: the driver/vehicle does    |                             |
   |    nothing. This can happen for     |                             |
   |    many reasons, for example when   |                             |
   |    the vehicle reaches the next     |                             |
   |    event's destination before the   |                             |
   |    start of its time window         |                             |
   |                                     |                             |
   |  * DELAY: *right before* the next   |                             |
   |    arrival. E.g. the vehicle and/or |                             |
   |    driver spends time unloading.    |                             |
   |                                     |                             |
---+-------------------------------------+-----------------------------+-->
   ^                                     ^                             ^
V[i-1].end                           V[i].start                    V[i].end
最后,下面介绍了如何在转换期间安排 TRAVEL、BREAKS、DELAY 和 WAIT。
- 不会重叠。
- DELAY 是唯一的,且必须是下次访问(或车辆结束)之前的连续时间段。因此,只需知道延迟时长即可知道其开始时间和结束时间。
- BREAKS 是连续且不重叠的时间段。并在回答中指定每个插播时间点的开始时间和时长。
- TRAVEL 和 WAIT 是“可抢占”状态:在转换期间,它们可能会被中断多次。客户可以假定行程会“尽快”完成,并使用“等待”填充剩余时间。
(复杂)示例:
                               TRANSITION[i]
--++-----+-----------------------------------------------------------++-->
  ||     |       |           |       |           |         |         ||
  ||  T  |   B   |     T     |       |     B     |         |    D    ||
  ||  r  |   r   |     r     |   W   |     r     |    W    |    e    ||
  ||  a  |   e   |     a     |   a   |     e     |    a    |    l    ||
  ||  v  |   a   |     v     |   i   |     a     |    i    |    a    ||
  ||  e  |   k   |     e     |   t   |     k     |    t    |    y    ||
  ||  l  |       |     l     |       |           |         |         ||
  ||     |       |           |       |           |         |         ||
--++-----------------------------------------------------------------++-->
| JSON 表示法 | 
|---|
| { "vehicleIndex": integer, "vehicleLabel": string, "vehicleStartTime": string, "vehicleEndTime": string, "visits": [ { object ( | 
| 字段 | |
|---|---|
| vehicleIndex | 
 执行路线的车辆,由其在源  | 
| vehicleLabel | 
 执行此路线的车辆的标签,等于  | 
| vehicleStartTime | 
 车辆开始行驶路线的时间。 时间戳采用 RFC3339 世界协调时间(UTC,即“祖鲁时”)格式,精确到纳秒,最多九个小数位。示例: | 
| vehicleEndTime | 
 车辆完成行程的时间。 时间戳采用 RFC3339 世界协调时间(UTC,即“祖鲁时”)格式,精确到纳秒,最多九个小数位。示例: | 
| visits[] | 
 表示路线的访问有序序列。visits[i] 是路线中的第 i 次访问。如果此字段为空,车辆会被视为未使用。 | 
| transitions[] | 
 路由的有序转换列表。 | 
| hasTrafficInfeasibilities | 
 如果  由于交通拥堵导致预计的旅行时间  | 
| routePolyline | 
 路线的编码多段线表示形式。仅当  | 
| breaks[] | 
 为执行此路线的车辆安排的休息时间。 | 
| metrics | 
 此路线的时长、距离和负载指标。 | 
| routeCosts | 
 路线费用,按费用相关的请求字段细分。键是相对于输入 OptimizeToursRequest 的 proto 路径,例如“model.shipments.pickups.cost”,值是相应费用字段生成的总费用,涵盖整个路线。换句话说,cost["model.shipments.pickups.cost"] 是路线中所有提货费用的总和。此处会详细报告模型中定义的所有费用,但与 TransitionAttributes 相关的费用除外,自 2022 年 1 月起,这些费用仅以汇总方式报告。 | 
| routeTotalCost | 
 路线的总费用。费用图中所有费用的总和。 | 
访问
在路线期间进行的访问。此访问对应于 Shipment 的取件或送货。
| JSON 表示法 | 
|---|
| {
  "shipmentIndex": integer,
  "isPickup": boolean,
  "visitRequestIndex": integer,
  "startTime": string,
  "loadDemands": {
    string: {
      object ( | 
| 字段 | |
|---|---|
| shipmentIndex | 
 来源  | 
| isPickup | 
 如果为 true,则表示相应到访与  | 
| visitRequestIndex | 
 
 | 
| startTime | 
 访问的开始时间。请注意,车辆可能会提前到达上门服务地点。时间与  时间戳采用 RFC3339 世界协调时间(UTC,即“祖鲁时”)格式,精确到纳秒,最多九个小数位。示例: | 
| loadDemands | 
 总访问加载需求,即运单和访问请求  | 
| detour | 
 由于在到达前往目的地之前,路线上还有其他要配送的运输包裹,以及由于时间范围而可能产生的等待时间,因此产生的额外绕道时间。如果访问是送餐,系统会根据相应的取货造访计算绕行时间,并且等于: 否则,它根据车辆  该时长以秒为单位,最多包含九个小数位,以“ | 
| shipmentLabel | 
 相应  | 
| visitLabel | 
 相应  | 
转换
路线上两个事件之间的转换。请参阅 ShipmentRoute 的说明。
如果车辆没有 startLocation 和/或 endLocation,则相应的行程指标为 0。
| JSON 表示法 | 
|---|
| { "travelDuration": string, "travelDistanceMeters": number, "trafficInfoUnavailable": boolean, "delayDuration": string, "breakDuration": string, "waitDuration": string, "totalDuration": string, "startTime": string, "routePolyline": { object ( | 
| 字段 | |
|---|---|
| travelDuration | 
 在此过渡期间的旅行时长。 该时长以秒为单位,最多包含九个小数位,以“ | 
| travelDistanceMeters | 
 转换期间移动的距离。 | 
| trafficInfoUnavailable | 
 通过  | 
| delayDuration | 
 应用于此转换的延迟时长的总和。延迟时间(如果有)会在下一个事件(光顾或车辆结束)开始前恰好  该时长以秒为单位,最多包含九个小数位,以“ | 
| breakDuration | 
 在此转换期间发生的休息时长(如果有)的总和。有关每个休息时间的开始时间和时长的详细信息存储在  该时长以秒为单位,最多包含九个小数位,以“ | 
| waitDuration | 
 此转换期间的等待时间。等待时长对应于空闲时间,不包括休息时间。另请注意,此等待时间可能会拆分为多个不连续的间隔时间。 该时长以秒为单位,最多包含九个小数位,以“ | 
| totalDuration | 
 转换的总时长(为方便起见提供)。等于: 
 该时长以秒为单位,最多包含九个小数位,以“ | 
| startTime | 
 此转换的开始时间。 时间戳采用 RFC3339 世界协调时间(UTC,即“祖鲁时”)格式,精确到纳秒,最多九个小数位。示例: | 
| routePolyline | 
 过渡期间所遵循路线的编码多段线表示形式。仅当  | 
| routeToken | 
 仅限输出。一个不透明令牌,可传递给 Navigation SDK 以在导航期间重构路线,并在重新路线时遵循创建路线时的原始意图。将此词元视为不透明 blob。请勿比较不同请求的此值,因为即使服务返回完全相同的路线,此值也可能会发生变化。只有当  | 
| vehicleLoads | 
 在此过渡期间的车辆载荷,对于此车辆的  第一次转换期间的负载是车辆路线的起始负载。然后,在每次访问后,系统都会添加或减去相应访问的  | 
EncodedPolyline
多段线的编码表示法。如需详细了解多段线编码,请参阅:https://developers.google.com/maps/documentation/utilities/polylinealgorithm https://developers.google.com/maps/documentation/javascript/reference/geometry#encoding。
| JSON 表示法 | 
|---|
| { "points": string } | 
| 字段 | |
|---|---|
| points | 
 表示多段线编码点的字符串。 | 
休息时间
表示执行 break 的数据。
| JSON 表示法 | 
|---|
| { "startTime": string, "duration": string } | 
| 字段 | |
|---|---|
| startTime | 
 休息时间的开始时间。 时间戳采用 RFC3339 世界协调时间(UTC,即“祖鲁时”)格式,精确到纳秒,最多九个小数位。示例: | 
| duration | 
 休息时长。 该时长以秒为单位,最多包含九个小数位,以“ |