其中在websocket的body中,定义了巡航服务数据交换协议,消息的结构框架如下:

以下为websocket的body内容举例,数据的格式为json格式:
{"id": 10011111, // 本条消息的id"qt": "xxxx", // 消息类型"ver": "1.0", // 协议版本号"prt": 1, // 协议类型,1 Json,2 Protocol Buffer"enc" : 1, // 加密方式,1 不加密,2 使用rsa加密"ts": 1696738704000,"data": {...}}
公共字段详细说明:
客户端上报消息举例:
{"id": 10011111,"qt": "auth","ver": "1.0","prt": 1,"enc" : 1,"ts": 1696738704000,"data": {"ak": "xxxxxxxxxxx","entity_id": "et_123"}}
字段说明:
服务端下发消息举例:
{"id": 10011112,"qt": "auth","ver": "1.0","prt": 1,"enc" : 1,"ts": 1696738704000,"data": {"status": 0,"message": "success","ack": 10011111,}}
字段说明:

例如客户端发送:
{"id": 10011111,"qt": "auth","ver": "1.0","prt": 1,"enc" : 2, // enc指定为2,代表这是一个带有rsa公钥的鉴权请求"ts": 1696738704000,"data": {"ak": "xxxxxx","entity_id": 111111,"rsa_puc": "gdfvfdnjidss" // 公钥记得通过urlencode,将换行符等特殊字符处理下}}
{"id": 10011111,"qt": "auth","ver": "1.0","prt": 1,"enc" : 2, // enc指定为2,代表需要用客户端保存的rsa私钥解密"ts": 1696738704000,"data": "vvvvvvvvvvvvvvvvvvvvvvvv" // rsa公钥加密后base64encode的数据,需要先base64decode然后rsa私钥解密}// data 用rsa私钥解密后的json结构{"status": 0,"message": "success","aes_key": "xxxxxxxxxxxxxxxxxxxxxxxx","aes_iv": "xxxxxxxxxxxxx","ack": 1111,}
{"id": 1234,"qt": "horizon","ver": "1","prt": 1,"enc" : 3, // enc指定为3,使用aes对称加密数据传输"ts": 1696738704000,"data": "zxcvvbddddcccccasdasdgfg" // 先base64decode,然后aes解密}
车辆启动时与服务端建立连接,然后开始按固定频率上报车辆位置数据。
消息内容举例:
{"id": 1234,"qt": "horizon","ver": "1","prt": 1,"enc" : 1,"ts": 1696738704000,"data": {"loc": {"x": 116.324523,"y": 40.345612,"ts": 1696738704000,"coordtype": 1,"speed": 23,"dir": 55,"car_dir": 60,"link_id": 1111111110,"link_offset": 11.0,"link_index": 1,}}}
字段说明:
如果使用百度webapi或sdk规划了路线(注意官网公版部分字段没有返回,需要通过商务合作获取特定版本),可以传入路线,服务将按照规划的路线进行探路。
消息内容举例:
{"route": {"type": 2,"session_id": "{\"codr\":\"02CDB5B2DA65BC9FEEA90FEF56D619CF|0_31.222520,121.627280_31.225630,121.642410_81\",\"loc\":\"nj\"}@654","mrsl": "\"g\":\"0_1\",\"w\":\"AAAA\",\"p\":\"1\",\"label\":\"8\",\"s\":\"0\",\"seq\":\"0\"","route_id": "17128094712920","steps": [],"route_rsp_field": ["link", "slope"],"linkids": [16187785020, 15238935340, 15239274420, 15239121070, 15238942420, 16315118100, 16600787520, 16600787510, 16600787490, 16600787500, 16532849300, 16532849290, 16505147200, 16869868490, 16869868840, 16532849280],"linklength": [118, 337, 17, 21, 122, 298, 28, 29, 21, 3, 78, 12, 12, 293, 61, 38]}}
字段说明:
当车辆前方出现路口时,服务端下发车辆前方的道路拓扑。
消息内容举例说明:
{"id": 1234,"qt": "horizon","ver": "1","prt": 1,"enc" : 1,"ts": 16445465677,"data": {"version": 321,"route_id": "17128094712920","path": [{"id": 8,"pid": 0,"offset": 0,"type": 0,"is_complex_intersection": 1,"relative_probability": 1,"is_part_of_route": true,"is_last_stub_at_offset": true,"turn_angle": 22.11,"pathclass": 1,"lanenums2e": 3,"lanenume2s": 0,"right_of_way": 1,"form_of_way": 0},{"id": 9,"pid": 8,"offset": 50,"type": 1,"is_complex_intersection": 1,"relative_probability": 1,"is_part_of_route": true,"is_last_stub_at_offset": true,"turn_angle": 22,"pathclass": 1,"lanenums2e": 3,"lanenume2s": 0,"right_of_way": 1,"form_of_way": 0},{"id": 10,"pid": 8,"offset": 50,"type": 0,"is_complex_intersection": 1,"relative_probability": 1,"is_part_of_route": true,"is_last_stub_at_offset": true,"turn_angle": 170,"pathclass": 1,"lanenums2e": 3,"lanenume2s": 0,"right_of_way": 1,"form_of_way": 0},{"id": 11,"pid": 8,"offset": 50,"type": 0,"is_complex_intersection": 1,"relative_probability": 1,"is_part_of_route": true,"is_last_stub_at_offset": true,"turn_angle": 90,"pathclass": 1,"lanenums2e": 3,"lanenume2s": 0,"right_of_way": 1,"form_of_way": 0},{"id": 6,"pid": 8,"offset": 50,"type": 0,"is_complex_intersection": 1,"relative_probability": 1,"is_part_of_route": true,"is_last_stub_at_offset": true,"turn_angle": 0,"pathclass": 1,"lanenums2e": 3,"lanenume2s": 0,"right_of_way": 1,"form_of_way": 0}]}}
上述消息表示如下图所示的车辆前方道路预测:

车辆行驶在红色path_id=8的main path上,该path为预测行驶路径,当遇到路口时,会优先选择直行作为预测方向继续往前探路;
从main path上延伸出path_id=9、path_id=10、path_id=11三条sub path,表示与main path有直接拓扑关系的道路;
路口处会从main path上摘取一段作为脱出path,其path_id=6,表示主路的延续。
假如车辆在路口前40m处,以此构建拓扑模型:
以path8的起点为零点,path9、path10、path11位于path8的offset 50m处;
车辆当前位置(将通过position消息下发)在path8上,位于path8的offset 10m处。

通过计算50m - 10m = 40m,可知车辆前方40m处有一个路口,分别延伸出path 9、10、11三条道路,车辆将沿着主路继续行驶。
字段说明:
下发局部路网上每条道路的属性,如道路等级、限速等。
消息内容举例说明:
{"id": 1234,"qt": "horizon","ver": "1","prt": 1,"enc" : 1,"ts": 1696738704000,"data": {"version": 321,"route_id": "17634593574890","max_send_length": 2000,"path": [{"id": 1,"pid": 0,"offset": 0,"type": 0,"is_complex_intersection": 1,"relative_probability": 1,"is_part_of_route": true,"is_last_stub_at_offset": true,"turn_angle": 22.11,"pathclass": 1,"lanenums2e": 3,"lanenume2s": 0,"right_of_way": 1,"form_of_way": 0}],"link": [{"path_id": 1,"link_id": 123234411,"offset": 20,"length": 100,"distance_to_pos": 10,"road_grade": 1,"form_of_way":1,"road_name":"沪杭公路辅路","pathclass": 1,"kind": [261,264],"uflag": 1,"lanenum": 3,"lanenume2s": 1,"speed_limit": 60,"speed_limit_type": 1,"shape": [[114.12341, 36.13211],[114.12342, 36.13212],[114.12343, 36.13213],[114.12344, 36.13214],],"is_complex_intersection": 1,"relative_probability": 1,"is_part_of_route": true,"ownership": 1,"link_index": 1}]}}
字段说明:
消息内容举例:
{"id": 1234,"qt": "horizon","ver": "1.0","prt": 1,"enc" : 1,"ts": 1696738704000,"data": {"route_id": "17128094712920","position": {"path_id": 1,"offset": 10.234,"speed": 12,"dir": 30.0,"gps_loc": [116.324523,40.34567],"gps_loc_time": 1696738704000,"rectify_loc": [116.324523,40.34567],"rectify_loc_time": 1696738704000,"link_id": 1233211231,"link_offset": 3.0,"probability": 0.8,"link_dir": 29.0,"elevated": 0},"version": 111}}
字段说明:
当车辆前方出现路口时,服务端先下发路线预测,完成后紧接着下发路线上的动态数据。
消息内容举例:
{"enc": 1,"id": 25,"prt": 1,"qt": "horizon","ts": 1709009041280,"ver": "1.0","data": {"route_id": "17089338650090","traffic_light": [// 一个红绿灯可能有多个方向的灯,例如直行、左转、右转等,返回为一个数组{ // 第一个灯"comfrom": 0,"distance_to_pos": 358.16125679016113,"loc": [121.64141865740267,31.266692544110214],"offset": 590.156005859375, // 灯的位置,offset相同表示同一个路口的红绿灯"on_route": 1,"path_id": 8,"link_id": 1233211231,"road_flow_direction": "12", // 灯管控的通行方向,此处为左转灯"simple_eight_direction":"12", // 左转"status": [ // 只有车辆前方一定范围内的灯会下发灯态,路线上其他的灯该数组为空// 第一个周期{"count_down": 56, // 倒计时56秒"lamp_status": 21, // 红灯状态"period": 56 // 置信区间为56秒,56秒后切下一个灯态,即使倒计时没到0也切},// 第二个周期{"count_down": 23, // 倒计时23秒"lamp_status": 23, // 绿灯状态"period": 23 // 置信区间为23秒,23秒后切下一个灯态},// 第三个周期{"count_down": 10000, // 倒计时未挖掘出来"lamp_status": 22, // 黄灯状态"period": 4 // 置信区间为4秒,4秒后切下一个灯态},// 第四个周期{"count_down": 93, // 倒计时93秒"lamp_status": 21, // 红灯状态"period": 93 // 置信区间为93秒,93秒后切下一个灯态}],"timestamp": 1709009028},{ // 第二个灯"comfrom": 0,"distance_to_pos": 358.16125679016113,"loc": [121.64141865740267,31.266692544110214],"offset": 590.156005859375,"on_route": 0,"path_id": 8,"link_id": 1233211231,"road_flow_direction": "99", // 此处没有挖出方向,实际是个掉头的灯"simple_eight_direction":"3", // 掉头"status": [{"count_down": 10000, // 没有挖掘出倒计时的情况"lamp_status": 11, // 灭灯状态"period": 5 // 置信区间为5s内可信},{"count_down": 10000,"lamp_status": 21,"period": 0},{"count_down": 10000,"lamp_status": 23,"period": 0},{"count_down": 10000,"lamp_status": 11,"period": 0}],"timestamp": 1709009028}],"version": 21}}
字段说明:
status字段为一个数组,代表一段连续时间内的多个灯态周期:


如上图车辆在offset 40m处,offset 50m处有一个路口,offset 1000m处有一个路口,有可能offset 50m路口由于缺少车辆轨迹无法挖掘到红绿灯动态,因此只能下发offset 1000m处路口红绿灯动态,当offset 50m处路口挖掘到红绿灯动态后,服务端会主动推送。
消息内容举例:
{"id": 10011111,"qt": "horizon","ver": "1.0","prt": 1,"enc" : 1,"ts": 1696738704000,"data": {"version": 321,"route_id": "17128094712920","event": [{"path_id": 1,"offset": 15.0,"length": 20.0,"distance_to_pos": 20,"type": 1,"type_desc": "封路","title": "道路施工","content": "当前道路因施工封闭","status": 6,"start_time": 1617073042,"offline_time": 1617073042,"update_time": 1617073042,"id": 1695624088389632,}]}}
字段说明:
消息内容举例:
{"id": 10011111,"qt": "horizon","ver": "1","prt": 1,"enc" : 1,"ts": 1696738704000,"data": {"version": 321,"route_id": "17128094712920","traffic": [{"path_id": 1,"offset": 10,"length": 40,"status": 1,"speed": 10}]}}
字段说明:
消息内容举例:
{"id": 10011111,"qt": "horizon","ver": "1","prt": 1,"enc" : 1,"ts": 1696738704000,"data": {"version": 2,"route_id": "","slope": [{"path_id": 1,"offset": [1, 20, 30, 40, 70, 70, 90],"step": [511,513,511,509,489,1023,511],// 两个70,第二个70是中断点,值是1023,指的是从70到90之间无坡度数据}]}}
字段说明:
// 合并前{"slope": [{"path_id": 1,"offset": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],"step": [501, 501, 501, 502, 503 ,501, 501, 501, 501, 1023, 1023, 1023]}]}// 合并后{"slope": [{"path_id": 1,"offset": [1, 4, 5, 6, 10],"step": [501, 502, 503, 501, 1023]}]}

坡度计算方法为使用ADAS后一属性点与当前属性点之间的距离和高程变化值作为反三角函数(arctanα)的输入,计算当前属性点的坡度值(弧度制),如下图所示。

消息内容举例:
{"id": 10011111,"qt": "horizon","ver": "1","prt": 1,"enc" : 1,"ts": 1696738704000,"data": {"version": 2,"route_id": "","curvature": [{"path_id": 1,"offset": [1, 2, 4, 7,7,20],"step": [511,514,520,544,1023,511],//两个7,第二个7是中断点,值是1023,指的是从7-20之间无数据。}]}}
字段说明:
// 合并前{"curvature": [{"path_id": 1,"offset": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],"step": [511, 511, 511, 514, 520, 511, 511, 511, 511, 1023, 1023, 1023]}]}// 合并后{"curvature": [{"path_id": 1,"offset": [1, 4, 5, 6, 10],"step": [511, 514, 520, 511, 1023]}]}
曲率计算采用轨迹拟合曲线的曲率作为道路线对应位置的曲率。为保证拟合曲线平滑,采用滑动窗口的机制,对轨迹做三阶多项式曲线拟合。在得出拟合曲线之后,再在属性点位置进行采样,获得道路线各属性点的曲率值,如下图所示。


曲率计算公式:

曲率的单位为1/m,属性点间距为1m,沿通行方向左转为正值,沿通行方向右转为负值。曲率经过第一步计算后得到浮点数,进一步四舍五入处理成保留8位小数的曲率值。曲率字段最终表达的是曲率的分级值,按照0.00001为一级进行分级表达。
协议输出方式:

消息内容举例:
{"id": 10011111,"qt": "horizon","ver": "1","prt": 1,"enc" : 1,"ts": 1696738704000,"data": {"version": 321,"route_id": "17128094712920","warning_info": [{"path_id": 1,"type_code": 32,"offset": 34.23,"loc": [116.324523,40.345612],"dir": 1,"link_id": 1233211231}]}}
字段说明:
车辆和服务端在双向通信时,用于反馈哪些消息已经收到了,已经收到的消息,如果没有变化将不会重复发送。
消息内容举例:
{"id": 10011111,"qt": "horizon","ver": "1","prt": 1,"enc" : 1,"ts": 1696738704000,"data": {"ack": [1111,2222,3333],}}
字段说明:
通过百度导航SDK或路线规划API规划路线,上报路线消息后,服务端可通过该消息下发路线上的全量属性数据。
消息内容举例:
{"id": 10011111,"qt": "horizon","ver": "1","prt": 1,"enc" : 1,"ts": 1696738704000,"data": {"route_info": {"route_id": "17128094712920","link": [{"kind": [2,12],"length": 69.0,"link_id": 16283162590,"offset": 4824.0,"road_grade": 0,"shape": [[121.643903,31.23782],[121.6439024,31.2376064],[121.6439046,31.2371984]],"speed_limit": 100,"speed_limit_type": 1,"traffic_status": {"fullfill": 0,"speed": 76.0,"status": 1,"update_time": 1747656895},"truck_limit_info": {"truck_speed_limit": {"speed": 80}}}],"slope": [{"path_id": 1,"offset": [1, 2, 3, 4, 5, 6, 7],"step": [3, 3, 3, 3, 3 ,3, 3],}],"curvature": [{"path_id": 1,"offset": [1, 2, 3, 4, 5, 6, 7],"step": [3, 3, 3, 3, 3, 3, 3],}]}}}
消息内容举例:
{"enc": 1,"id": 25,"prt": 1,"qt": "horizon","ts": 1709009041280,"ver": "1.0","data": {"route_id": "","version": 4,"lane_arrow": [{"path_id": 8,"offset": 180.2,"linkid": 123450,"direction": "1,13,12","loc": [116.312345, 39.987654],"distance_to_pos": 50.5,"lane_type":"1,1,1"},{"path_id": 8,"offset": 245.8,"linkid": 123452,"direction": "1,13","loc": [116.31321, 39.988901],"distance_to_pos": 116.1,"lane_type":"1,1"}]}}
字段说明:
使用方法:
车道级箭头信息中,每个 lane_arrow 都包含 path_id、offset 和 distance_to_pos:path_id 为车信所在的道路 ID,offset 为车信在该道路上的偏移位置(单位:米),distance_to_pos 为车信起点到当前车辆位置的距离。终端同时会收到车辆实时位置 position 信息,其中的 path_id 和 offset 分别表示车辆当前所在的道路 ID,以及车辆在该道路上的偏移位置。
车道级箭头信息属于静态数据,不会实时刷新,因此采用增量下发机制:构造 horizon 视野时,先下发前方约 2 公里范围内的 lane_arrow 数据;此后车辆每前进约 200 米,再增量下发前方约 200 米范围内的新数据。因此,推荐在使用箭头数据时,优先用当前 position 中的 path_id 和 offset 去匹配车道级箭头信息中的 path_id 和 offset,从而确定当前应关注的车信位置;匹配时同样要求两者的 version 一致。
此外,也可以基于 distance_to_pos 实时计算车辆与车信之间的剩余距离:在 version、path_id 一致的前提下,用车辆 offset 的变化量对 distance_to_pos 做实时扣减,即可得到最新距离。例如,某条箭头数据下发时 distance_to_pos=1800、path_id=8、offset=1850,此时车辆位于 path_id=8、offset=50;下一时刻车辆仍在同一路径上,且 offset 更新为 90,则车辆与该车信的实际距离为 1800 - (90 - 50) = 1760 米。

消息内容举例:
{"enc": 1,"id": 25,"prt": 1,"qt": "horizon","ts": 1709009041280,"ver": "1.0","data": {"route_id": "","version": 2,"camera_list": [{"distance_to_pos": 100.3,"type": 1,"speed_limit": 80,"loc": [116.404,39.915],"linkid": 123456789,"offset": 300.2315,"path_id": 8,"angle":86},{"distance_to_pos": 500.2,"type": 2,"speed_limit": 60,"loc": [116.405,39.916],"linkid": 123456790,"offset": 800.7834,"path_id": 8,"angle":177}]}}
字段说明:
使用方法:
电子眼信息中,camera_list 的每个电子眼都包含 path_id、offset 和 distance_to_pos:path_id 为摄像头所在的道路 ID,offset 为摄像头在该道路上的偏移位置(单位:米),distance_to_pos 为摄像头到当前车辆位置的距离。终端同时会收到车辆实时位置 position 信息,其中的 path_id 和 offset 分别表示车辆当前所在的道路 ID,以及车辆在该道路上的偏移位置。
电子眼信息属于静态数据,不会实时刷新,因此采用增量下发机制:构造 horizon 视野时,先下发前方约 2 公里范围内的 camera_list 数据;此后车辆每前进约 200 米,再增量下发前方约 200 米范围内的新数据。因此,推荐在使用电子眼数据时,优先用当前 position 中的 path_id 和 offset 去匹配电子眼信息中的 path_id 和 offset,从而确定当前应关注的电子眼位置;匹配时同样要求两者的 version 一致。
此外,也可以基于 distance_to_pos 实时计算车辆与电子眼之间的剩余距离:在 version、path_id 一致的前提下,用车辆 offset 的变化量对 distance_to_pos 做实时扣减,即可得到最新距离。例如,某条电子眼数据下发时 distance_to_pos=1800、path_id=8、offset=1850,此时车辆位于 path_id=8、offset=50;下一时刻车辆仍在同一路径上,且 offset 更新为 90,则车辆与该电子眼的实际距离为 1800 - (90 - 50) = 1760 米。
为了优化路径计算的速度,规划合理路径,人为根据相应规则,对道路定义不同的等级,体现了优化的路网。FC 分为 5 个级别,分别为 FC1、FC2、FC3、FC4 和 FC6。FC1 为最高级别,FC6 为最低级别,FC0为未知级别。每个级别具体定义如下表:
该部分为新的映射关系:
上一篇
下一篇