本章结束后,你将能够:
想象一下,在晚高峰的北京国贸,数千名骑手同时在配送,每秒都有上万次路径查询请求。一个骑手站在写字楼下,需要知道去18层取餐要多久;另一个骑手正在规划去3公里外最快的路线;调度系统需要实时计算10000个骑手到5000个商家的距离矩阵…这就是美团LBS系统每天面对的挑战。
LBS(Location Based Service)系统是超脑的”眼睛”和”地图”,它将真实世界的地理空间映射为可计算的数字世界。没有精准的地理信息,再智能的调度算法也无法落地;没有高效的路径规划,再优秀的时间预估也会失准。本章将深入剖析这个日调用量达760亿次的地理信息引擎。
LBS系统在整个超脑架构中扮演着基础设施的角色,它是连接物理世界与数字世界的桥梁:
┌─────────────────────────────────────────────────────────┐
│ 业务决策层 │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │调度引擎 │ │ETA系统 │ │定价系统 │ │规划引擎 │ │
│ └────┬────┘ └────┬────┘ └────┬────┘ └────┬────┘ │
│ │ │ │ │ │
│ └────────────┴────────────┴────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────┐ │
│ │ LBS服务层 │ │
│ └──────────────────┘ │
└─────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ LBS核心能力 │
├─────────────────────────────────────────────────────────┤
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │地址服务 │ │路径规划 │ │地理围栏 │ │
│ ├──────────┤ ├──────────┤ ├──────────┤ │
│ │·地址解析 │ │·多模式 │ │·围栏判定 │ │
│ │·地址纠错 │ │·实时路况 │ │·范围查询 │ │
│ │·POI管理 │ │·室内导航 │ │·区域管理 │ │
│ └──────────┘ └──────────┘ └──────────┘ │
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │距离计算 │ │轨迹服务 │ │地图渲染 │ │
│ ├──────────┤ ├──────────┤ ├──────────┤ │
│ │·直线距离 │ │·轨迹存储 │ │·热力图 │ │
│ │·路网距离 │ │·轨迹纠偏 │ │·覆盖图 │ │
│ │·时间距离 │ │·轨迹分析 │ │·实时位置 │ │
│ └──────────┘ └──────────┘ └──────────┘ │
└─────────────────────────────────────────────────────────┘
LBS系统需要提供的核心能力可以用一个能力矩阵来描述:
| 能力维度 | 基础能力 | 进阶能力 | 智能化能力 |
|---|---|---|---|
| 地址 | 地址解析、标准化 | 模糊匹配、纠错 | 语义理解、自动补全 |
| 路径 | 最短路径 | 多约束路径、实时路况 | 个性化路径、预测规划 |
| 围栏 | 点面判定 | 动态围栏、复杂多边形 | 智能扩缩、自动优化 |
| 距离 | 直线距离 | 路网距离、步行距离 | 时间距离、成本距离 |
| 轨迹 | 轨迹存储 | 轨迹压缩、纠偏 | 异常检测、模式挖掘 |
根据公开数据,美团LBS系统需要支撑的性能指标令人震撼:
性能指标金字塔
╱╲
╱ ╲ 峰值QPS: 400万
╱ ╲
╱──────╲ 日调用量: 760亿
╱ ╲
╱──────────╲ 每小时路径规划: 29亿
关键延迟要求:
- 地址解析: < 5ms (P99)
- 路径规划: < 10ms (P99)
- 围栏判定: < 1ms (P99)
- 距离计算: < 1ms (P99)
LBS系统作为基础服务,需要为上层业务提供统一、稳定、高效的接口:
接口设计原则:
1. 统一协议:所有接口采用统一的RPC协议(如Thrift/gRPC)
2. 批量优化:支持批量查询,减少网络开销
3. 缓存友好:接口设计考虑缓存命中率
4. 降级方案:每个接口都有降级策略
5. 监控完备:接口级别的监控和报警
核心接口示例:
// 地址解析接口
service AddressService {
// 批量地址解析
AddressResult batchParse(List<string> addresses);
// 地址标准化
StandardAddress standardize(RawAddress addr);
// POI查询
List<POI> searchPOI(Location center, int radius);
}
// 路径规划接口
service RouteService {
// 单点到单点路径
Route planRoute(Location from, Location to, RouteOptions options);
// 多点路径规划(TSP问题)
MultiRoute planMultiRoute(List<Location> points, Constraints constraints);
// 距离矩阵计算
DistanceMatrix calcDistanceMatrix(List<Location> origins, List<Location> destinations);
}
// 围栏服务接口
service GeofenceService {
// 判定点是否在围栏内
bool contains(Location point, GeofenceId fence);
// 查询点所在的所有围栏
List<GeofenceId> queryFences(Location point);
// 范围查询
List<POI> rangeQuery(Location center, Shape shape, Filter filter);
}
## 7.2 五级地址库体系
### 7.2.1 地址结构化设计
美团的五级地址库是精确配送的基石。传统地址系统只能定位到小区或大楼,而外卖配送需要精确到楼层甚至房间。五级地址体系的设计理念:
五级地址层次结构 ┌─────────────────────────────────────────────────────┐ │ Level 1: 城市 │ │ (City: 北京市) │ └──────────────────────┬──────────────────────────────┘ │ ┌──────────────────────▼──────────────────────────────┐ │ Level 2: 区域 │ │ (District: 朝阳区) │ └──────────────────────┬──────────────────────────────┘ │ ┌──────────────────────▼──────────────────────────────┐ │ Level 3: 道路/小区 │ │ (Road/Community: 建国路88号) │ └──────────────────────┬──────────────────────────────┘ │ ┌──────────────────────▼──────────────────────────────┐ │ Level 4: 楼宇 │ │ (Building: SOHO现代城A座) │ └──────────────────────┬──────────────────────────────┘ │ ┌──────────────────────▼──────────────────────────────┐ │ Level 5: 楼层/门牌 │ │ (Floor/Room: 18层1801室) │ └─────────────────────────────────────────────────────┘
数据结构设计: { “addressId”: “110105001234567890”, // 18位唯一ID “level1”: { “code”: “110000”, “name”: “北京市”, “center”: [116.405285, 39.904989], “boundary”: {…} // GeoJSON格式边界 }, “level2”: { “code”: “110105”, “name”: “朝阳区”, “parentCode”: “110000” }, “level3”: { “code”: “110105001”, “name”: “建国路”, “number”: “88号”, “type”: “ROAD” // ROAD/COMMUNITY/MALL }, “level4”: { “code”: “110105001001”, “name”: “SOHO现代城A座”, “entrances”: [ // 多入口信息 {“type”: “MAIN”, “location”: [116.4753, 39.9042]}, {“type”: “SIDE”, “location”: [116.4755, 39.9041]} ], “elevators”: 6, // 电梯数量 “floors”: 28 // 总楼层 }, “level5”: { “code”: “110105001001018001”, “floor”: 18, “room”: “1801”, “walkTime”: 120 // 从主入口步行时间(秒) } }
### 7.2.2 地址解析与标准化
用户输入的地址往往是非结构化的自然语言,需要强大的解析能力:
地址解析流程:
原始输入: “朝阳建国路soho现代城a座18楼美团外卖” │ ▼ ┌──────────────────────┐ │ 1. 预处理清洗 │ │ 去除特殊字符、统一大小写│ └───────────┬──────────┘ │ ▼ ┌──────────────────────┐ │ 2. 分词与标注 │ │ 使用NER识别地址要素 │ └───────────┬──────────┘ │ ▼ ┌──────────────────────┐ │ 3. 地址要素抽取 │ │ 区域/道路/楼宇/楼层 │ └───────────┬──────────┘ │ ▼ ┌──────────────────────┐ │ 4. 候选地址匹配 │ │ 模糊匹配+相似度计算 │ └───────────┬──────────┘ │ ▼ ┌──────────────────────┐ │ 5. 歧义消解 │ │ 上下文+历史订单辅助 │ └───────────┬──────────┘ │ ▼ 标准化输出: { “formatted”: “北京市朝阳区建国路88号SOHO现代城A座18层”, “addressId”: “110105001001018000”, “confidence”: 0.95, “alternates”: […] // 备选地址 }
关键技术点:
实现楼层级精度需要解决室内定位和时间估算问题:
楼层时间模型:
楼层配送时间 = 电梯等待时间 + 电梯运行时间 + 步行时间
1. 电梯等待时间建模:
- 基于时段的泊松分布
- 考虑楼层热度(如1楼、餐饮楼层)
- 高峰期动态调整
2. 电梯运行时间:
- 楼层差 × 单层时间
- 考虑停靠概率
- 区分直达和站站停
3. 步行时间网格:
楼层内步行时间热力图
┌─────────────────────┐
│ 30 35 40 45 50 │ 秒
│ 25 20 25 30 35 │
│ 20 15 10 15 20 │
│ 25 20 15 20 25 │
│ 30 25 20 25 30 │
└─────────────────────┘
基于历史轨迹学习每个区域的步行时间
楼宇画像系统:
{
"buildingId": "B000A6GQ61",
"profile": {
"type": "OFFICE", // OFFICE/RESIDENTIAL/MALL
"floors": 28,
"elevators": {
"count": 6,
"speed": 2.5, // m/s
"avgWaitTime": {
"morning": 45, // 秒
"noon": 120,
"evening": 60
}
},
"security": {
"needRegister": true,
"avgTime": 30 // 登记时间
},
"peakHours": ["11:30-13:00", "18:00-19:30"],
"specialNotes": "负一层美食广场,18-22层为美团办公区"
}
}
基于海量历史数据的地址智能纠错:
纠错策略层次:
1. 字符级纠错(拼写错误):
"建国陆" → "建国路"
使用编辑距离 + 拼音相似度
2. 语义级纠错(理解错误):
"soho三期" → "SOHO现代城"
基于知识图谱的实体链接
3. 上下文纠错(关联推理):
用户历史: ["朝阳SOHO", "建外SOHO", "??SOHO"]
商家位置: 建国路
推理结果: "现代城SOHO"
4. 协同过滤纠错:
相似用户的地址模式
相同商圈的地址分布
地址补全决策树:
输入片段
│
┌─────────┴─────────┐
│ │
有历史订单 无历史订单
│ │
┌─────┴─────┐ ┌─────┴─────┐
│ │ │ │
同商家 不同商家 热门地址 冷门地址
│ │ │ │
优先推荐 参考推荐 通用推荐 模糊匹配
地址纠错的核心挑战在于平衡准确性和用户体验。过度纠正可能导致错误的地址替换,而纠正不足又会增加配送难度。美团的解决方案是构建多层次的置信度体系:
置信度分层策略:
纠错知识库构建:系统维护了一个包含千万级别名、简称、错别字的映射库。这个知识库通过以下方式持续更新:
实时学习机制:当某个地址纠错被多次确认后,系统会自动提升该纠错规则的权重,实现自我进化。
地理围栏(Geofence)是LBS系统的核心概念,它定义了商家的配送范围、骑手的工作区域、以及各种地理相关的业务规则:
围栏类型层次结构:
┌─────────────────────────────────────────────────────┐
│ 围栏类型分类 │
├─────────────────────────────────────────────────────┤
│ │
│ 业务围栏 物理围栏 │
│ ├─ 配送围栏 ├─ 行政区划 │
│ ├─ 营销围栏 ├─ 商圈边界 │
│ ├─ 价格围栏 ├─ 道路网格 │
│ └─ 服务围栏 └─ 建筑轮廓 │
│ │
│ 动态围栏 静态围栏 │
│ ├─ 天气围栏 ├─ 基础配送范围 │
│ ├─ 时段围栏 ├─ 禁行区域 │
│ └─ 运力围栏 └─ 特殊区域 │
└─────────────────────────────────────────────────────┘
商家配送围栏数据结构:
{
"merchantId": "M1234567",
"fences": [
{
"fenceId": "F001",
"type": "DELIVERY",
"priority": 1,
"shape": {
"type": "POLYGON",
"coordinates": [
[[116.4741, 39.9041], [116.4751, 39.9041], ...]
]
},
"properties": {
"minOrder": 20, // 起送价
"deliveryFee": 5, // 配送费
"maxDistance": 3000, // 最大配送距离(米)
"estimatedTime": 30 // 预估配送时间(分)
},
"timeRules": [
{
"dayOfWeek": [1,2,3,4,5], // 周一到周五
"timeRange": "11:00-14:00",
"adjustment": {
"deliveryFee": 3, // 高峰期加价
"estimatedTime": 45
}
}
],
"excludeAreas": [ // 排除区域(如湖泊、禁区)
{
"type": "CIRCLE",
"center": [116.4745, 39.9045],
"radius": 100
}
]
}
]
}
围栏计算优化技术:
美团每天需要处理数亿次的围栏判定请求,传统的点与多边形判定算法(如射线法)在如此规模下会成为性能瓶颈。优化方案包括:
配送范围不是一成不变的,需要根据实时运力、天气、交通等因素动态调整:
动态调整决策流程:
实时信号输入
┌────────────────┼────────────────┐
│ │ │
运力状态 天气状况 交通状况
│ │ │
▼ ▼ ▼
运力热力图 恶劣天气区域 拥堵路段
│ │ │
└────────────────┼────────────────┘
│
┌──────▼──────┐
│ 决策引擎 │
└──────┬──────┘
│
┌────────────────┼────────────────┐
│ │ │
缩小范围 维持现状 扩大范围
(运力不足) (供需平衡) (运力充足)
动态调整策略:
POI(Point of Interest)是地理信息系统的基础数据,美团维护着数千万个POI:
POI分类体系:
一级分类 二级分类 三级分类
├─ 餐饮 ├─ 中餐 ├─ 川菜
│ │ ├─ 粤菜
│ │ └─ ...
│ ├─ 西餐 ├─ 法国菜
│ │ ├─ 意大利菜
│ │ └─ ...
│ └─ 快餐 ├─ 汉堡
│ └─ ...
├─ 购物 ├─ 超市 ├─ 大型超市
│ ├─ 便利店 ├─ 24小时便利店
│ └─ ... └─ ...
├─ 生活服务 ├─ 美容 ├─ 美发
│ ├─ 洗衣 ├─ 干洗
│ └─ ... └─ ...
└─ ... └─ ... └─ ...
POI数据模型:
{
"poiId": "P1234567890",
"name": "海底捞(国贸店)",
"category": {
"level1": "餐饮",
"level2": "中餐",
"level3": "火锅"
},
"location": {
"lng": 116.4752,
"lat": 39.9042,
"address": "北京市朝阳区建国路88号SOHO现代城",
"addressId": "110105001001000000"
},
"attributes": {
"businessHours": "10:00-22:00",
"avgPrice": 120,
"rating": 4.8,
"phone": "010-12345678",
"images": [...],
"tags": ["网红店", "需排队", "有包间"]
},
"spatial": {
"entrance": [[116.4752, 39.9042]],
"outline": {...}, // 建筑轮廓
"floor": 3,
"area": 500 // 平方米
},
"metadata": {
"createTime": "2020-01-01T00:00:00Z",
"updateTime": "2024-01-01T00:00:00Z",
"source": "MERCHANT_UPLOAD", // 数据来源
"verified": true,
"confidence": 0.99
}
}
POI数据采集与更新:
POI数据的准确性直接影响用户体验,美团通过多种方式保持POI数据的新鲜度:
POI去重与融合:
同一个实体可能有多个数据源,需要智能去重和融合:
POI融合决策矩阵:
数据源优先级:
商家上传 > 官方验证 > 骑手采集 > 用户反馈 > 自动挖掘
冲突解决策略:
┌─────────────┬──────────────┬──────────────┬──────────────┐
│ 属性类型 │ 位置信息 │ 营业时间 │ 联系方式 │
├─────────────┼──────────────┼──────────────┼──────────────┤
│ 解决方案 │ 加权平均 │ 最新优先 │ 商家优先 │
│ 置信度权重 │ 基于来源 │ 基于时间 │ 基于验证 │
└─────────────┴──────────────┴──────────────┴──────────────┘
围栏计算是LBS系统的性能瓶颈之一,需要精心的算法设计和工程优化:
围栏判定优化层次:
第一层:粗筛(毫秒级)
├─ Geohash网格索引
├─ 外接矩形过滤
└─ 空间R-Tree索引
第二层:精判(微秒级)
├─ 射线法判定
├─ 向量叉积法
└─ GPU并行计算
第三层:缓存(纳秒级)
├─ 热点区域缓存
├─ 用户历史缓存
└─ 会话级缓存
高性能围栏引擎架构:
为了支撑每秒百万级的围栏查询,美团设计了分布式围栏引擎:
围栏索引数据结构:
// 空间索引节点
struct SpatialNode {
Rectangle mbr; // 最小外接矩形
vector<FenceId> fences; // 围栏ID列表
vector<SpatialNode*> children; // 子节点
bool contains(Point p) {
// 快速判定点是否在MBR内
return p.x >= mbr.minX && p.x <= mbr.maxX &&
p.y >= mbr.minY && p.y <= mbr.maxY;
}
};
// 围栏判定优化
class FenceEngine {
SpatialIndex index; // 空间索引
Cache<Point, FenceList> cache; // 判定缓存
FenceList query(Point p) {
// 1. 查缓存
if (cache.contains(p)) {
return cache.get(p);
}
// 2. 空间索引粗筛
auto candidates = index.query(p);
// 3. 精确判定
FenceList results;
for (auto fence : candidates) {
if (fence.contains(p)) {
results.add(fence);
}
}
// 4. 更新缓存
cache.put(p, results);
return results;
}
};
路径规划是LBS系统的核心算法,直接影响配送效率和用户体验。美团的路径规划需要处理每小时29亿次的规划请求,同时保证10ms以内的响应时间。
不同的交通模式有着截然不同的路径特征和约束条件:
多模式路径特征对比:
┌──────────┬────────────┬────────────┬────────────┬────────────┐
│ 模式 │ 步行 │ 自行车 │ 电动车 │ 汽车 │
├──────────┼────────────┼────────────┼────────────┼────────────┤
│ 速度 │ 5km/h │ 15km/h │ 25km/h │ 30km/h │
│ 可达性 │ 最高 │ 高 │ 中 │ 低 │
│ 楼梯 │ ✓ │ ✗ │ ✗ │ ✗ │
│ 逆行 │ ✓ │ 部分 │ ✗ │ ✗ │
│ 人行道 │ ✓ │ ✓ │ 部分 │ ✗ │
│ 停车 │ 无需 │ 方便 │ 需要 │ 困难 │
│ 天气影响 │ 高 │ 高 │ 中 │ 低 │
└──────────┴────────────┴────────────┴────────────┴────────────┘
路网建模:
Graph = {
nodes: [
{
id: "N001",
location: [116.4752, 39.9042],
type: "INTERSECTION", // 交叉口
elevation: 0, // 海拔
connections: [...]
}
],
edges: [
{
id: "E001",
from: "N001",
to: "N002",
distance: 150, // 米
modes: ["WALK", "BIKE", "EBIKE"],
properties: {
width: 3.5, // 道路宽度
slope: 0.02, // 坡度
surface: "ASPHALT", // 路面材质
traffic: "LIGHT", // 交通状况
restricted: false // 是否限行
},
costs: {
WALK: 120, // 步行耗时(秒)
BIKE: 36, // 自行车耗时
EBIKE: 22 // 电动车耗时
}
}
]
}
多模式路径规划算法:
美团采用了改进的A*算法,针对不同交通模式定制化优化:
# 多模式路径规划核心算法
def multiModalRoute(start, end, mode, constraints):
# 1. 初始化
openSet = PriorityQueue()
openSet.add(start, 0)
cameFrom = {}
gScore = {start: 0}
fScore = {start: heuristic(start, end, mode)}
# 2. 搜索主循环
while not openSet.empty():
current = openSet.pop()
if current == end:
return reconstructPath(cameFrom, current)
# 3. 遍历邻居节点
for neighbor in getNeighbors(current, mode):
# 计算通过当前节点到邻居的成本
tentativeGScore = gScore[current] + \
getCost(current, neighbor, mode, constraints)
# 4. 剪枝优化
if tentativeGScore < gScore.get(neighbor, INF):
# 记录路径
cameFrom[neighbor] = current
gScore[neighbor] = tentativeGScore
fScore[neighbor] = tentativeGScore + \
heuristic(neighbor, end, mode)
# 加入开放集合
if neighbor not in openSet:
openSet.add(neighbor, fScore[neighbor])
return None # 无可达路径
# 成本计算函数(考虑多种因素)
def getCost(from, to, mode, constraints):
baseCost = edge.costs[mode]
# 实时路况调整
trafficFactor = getTrafficFactor(edge, currentTime)
# 天气影响
weatherFactor = getWeatherFactor(mode, currentWeather)
# 用户偏好(如避开主路)
preferenceFactor = getPreferenceFactor(edge, constraints)
# 安全系数(夜间、事故路段等)
safetyFactor = getSafetyFactor(edge, currentTime)
return baseCost * trafficFactor * weatherFactor * \
preferenceFactor * safetyFactor
实时路况是影响路径规划质量的关键因素。美团通过多源数据融合构建实时路况图:
路况数据源架构:
┌─────────────────────────────────────────────────────────┐
│ 实时路况融合系统 │
├─────────────────────────────────────────────────────────┤
│ │
│ 数据源层 处理层 输出层 │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │骑手轨迹 │────────▶│ │ │ │ │
│ ├──────────┤ │ 数据 │ │ 路况 │ │
│ │用户反馈 │────────▶│ 清洗 │─────▶│ 融合 │ │
│ ├──────────┤ │ 标准化 │ │ 模型 │ │
│ │第三方数据│────────▶│ │ │ │ │
│ ├──────────┤ └──────────┘ └──────────┘ │
│ │IoT传感器 │────────▶ 实时流处理 │ │
│ └──────────┘ ▼ │
│ ┌──────────────┐ │
│ │ 路况图输出 │ │
│ │ (5秒更新) │ │
│ └──────────────┘ │
└─────────────────────────────────────────────────────────┘
路况等级定义:
Level 1: 畅通 (绿色) - 实际速度 > 期望速度 * 0.9
Level 2: 基本畅通 (黄色) - 实际速度 > 期望速度 * 0.7
Level 3: 轻度拥堵 (橙色) - 实际速度 > 期望速度 * 0.5
Level 4: 中度拥堵 (红色) - 实际速度 > 期望速度 * 0.3
Level 5: 严重拥堵 (深红) - 实际速度 < 期望速度 * 0.3
路况预测模型:
除了实时路况,美团还构建了路况预测模型,预测未来30分钟的路况变化:
# 路况预测模型架构
class TrafficPredictor:
def __init__(self):
self.historical_patterns = {} # 历史模式
self.event_calendar = {} # 事件日历
self.weather_forecast = {} # 天气预报
def predict(self, road_segment, future_time):
# 1. 历史同期路况
historical = self.getHistoricalPattern(
road_segment,
future_time.weekday,
future_time.hour
)
# 2. 趋势分析
trend = self.analyzeTrend(road_segment, last_30_minutes)
# 3. 事件影响(演唱会、球赛等)
event_impact = self.getEventImpact(road_segment, future_time)
# 4. 天气影响
weather_impact = self.getWeatherImpact(
self.weather_forecast[future_time]
)
# 5. 融合预测
prediction = self.fusePrediction(
historical * 0.4 +
trend * 0.3 +
event_impact * 0.2 +
weather_impact * 0.1
)
return prediction
外卖配送的”最后100米”往往是最复杂的,特别是在大型商场、写字楼等室内场景:
室内导航技术栈:
1. 室内地图构建
├─ 楼层平面图数字化
├─ POI标注(电梯、楼梯、商铺)
├─ 通行区域识别
└─ 障碍物标记
2. 室内定位技术
├─ WiFi指纹定位
├─ 蓝牙Beacon
├─ 地磁定位
└─ 惯性导航(IMU)
3. 路径规划算法
├─ 多楼层路径搜索
├─ 电梯等待时间估算
├─ 楼梯vs电梯决策
└─ 拥挤度避让
室内导航数据结构:
{
"buildingId": "B001",
"floors": [
{
"level": 1,
"map": {
"image": "floor1.png",
"scale": 0.1, // 米/像素
"rotation": 0
},
"walkableArea": [
// 多边形定义的可行走区域
[[100, 100], [200, 100], [200, 200], [100, 200]]
],
"pois": [
{
"id": "E01",
"type": "ELEVATOR",
"location": [150, 150],
"connections": [2, 3, 4] // 连接楼层
},
{
"id": "S01",
"type": "STAIR",
"location": [180, 150],
"connections": [0, 2]
}
],
"shops": [
{
"id": "SHOP001",
"name": "星巴克",
"entrance": [120, 130],
"category": "咖啡店"
}
]
}
]
}
室内外无缝切换:
# 室内外导航切换逻辑
class HybridNavigator:
def navigate(self, start, end):
# 1. 判断起终点位置
startIndoor = self.isIndoor(start)
endIndoor = self.isIndoor(end)
if not startIndoor and not endIndoor:
# 纯室外导航
return self.outdoorRoute(start, end)
elif startIndoor and endIndoor and \
self.sameBuilding(start, end):
# 同建筑物内导航
return self.indoorRoute(start, end)
else:
# 室内外混合导航
segments = []
if startIndoor:
# 室内到建筑物出口
exit = self.findNearestExit(start)
segments.append(self.indoorRoute(start, exit))
start = exit
# 室外路径
if endIndoor:
entrance = self.findBestEntrance(end)
segments.append(self.outdoorRoute(start, entrance))
# 入口到室内终点
segments.append(self.indoorRoute(entrance, end))
else:
segments.append(self.outdoorRoute(start, end))
return self.mergeSegments(segments)
骑手在配送过程中可能因为各种原因偏离规划路径,系统需要实时检测并做出响应:
偏离检测状态机:
┌─────────┐
│ 正常 │
└────┬────┘
│
▼
┌──────────────────┐
│ 检测到位置偏移 │
└─────────┬────────┘
│
判定偏离程度
│
┌─────────┼─────────┐
│ │ │
▼ ▼ ▼
轻微偏离 中度偏离 严重偏离
│ │ │
▼ ▼ ▼
继续监控 建议返回 强制重规划
偏离检测算法:
def detectDeviation(currentLocation, plannedPath, threshold):
# 1. 计算到规划路径的垂直距离
distance = calculatePerpendicularDistance(
currentLocation,
plannedPath
)
# 2. 计算偏离角度
if len(recentLocations) >= 3:
movingDirection = calculateDirection(recentLocations)
plannedDirection = getPlannedDirection(plannedPath)
angle = angleDifference(movingDirection, plannedDirection)
# 3. 综合判定
if distance > threshold.distance:
return "DISTANCE_DEVIATION"
elif angle > threshold.angle:
return "DIRECTION_DEVIATION"
elif self.isMovingAway(currentLocation, destination):
return "WRONG_DIRECTION"
else:
return "ON_TRACK"
# 重规划策略
def replanStrategy(deviation, currentLocation, destination):
if deviation == "MINOR":
# 软提醒,不强制
return {
"action": "SUGGEST",
"message": "建议返回规划路线"
}
elif deviation == "MODERATE":
# 提供返回路径
returnPath = planPath(currentLocation, nearestPointOnPath)
return {
"action": "RETURN_PATH",
"path": returnPath
}
elif deviation == "SEVERE":
# 完全重新规划
newPath = planPath(currentLocation, destination)
return {
"action": "REPLAN",
"path": newPath,
"reason": "严重偏离原路径"
}
智能重规划决策:
重规划不是简单地计算新路径,还需要考虑多种业务因素:
class SmartReplanner:
def shouldReplan(self, context):
# 评估重规划的收益和成本
factors = {
"time_saved": self.estimateTimeSaved(context),
"distance_saved": self.estimateDistanceSaved(context),
"delivery_risk": self.assessDeliveryRisk(context),
"user_experience": self.predictUserImpact(context),
"rider_effort": self.estimateRiderEffort(context)
}
# 加权决策
score = (
factors["time_saved"] * 0.3 +
factors["distance_saved"] * 0.2 +
factors["delivery_risk"] * 0.3 +
factors["user_experience"] * 0.15 +
factors["rider_effort"] * 0.05
)
return score > REPLAN_THRESHOLD
def replan(self, context):
# 生成多个候选路径
candidates = []
# 最短路径
candidates.append(self.shortestPath(
context.current,
context.destination
))
# 最快路径(考虑实时路况)
candidates.append(self.fastestPath(
context.current,
context.destination,
context.traffic
))
# 最安全路径(避开事故多发区)
candidates.append(self.safestPath(
context.current,
context.destination
))
# 选择最优路径
return self.selectBest(candidates, context)