[Vroom] 位置与矩阵 | 路由集成 | 抽象,解耦与通信

第三章:位置与矩阵

欢迎回到 VROOM !

第一章:输入与问题定义中我们学习了如何描述整体问题框架,在第二章:任务与运输工具中我们聚焦于核心实体------任务(Jobs )与运输工具(Vehicles)。

现在我们将解析路径规划中不可或缺的关键要素:如何在任务执行位置与运输工具起止点之间建立移动关系,这正是位置 (Locations)与矩阵(Matrices)的协同作用。

设想我们有一辆从仓库出发的配送卡车需要访问两个客户点。要规划最优路线,必须明确以下移动参数:

  1. 仓库至第一个客户点的耗时/距离
  2. 客户点之间的移动参数
  3. 返回仓库的移动参数

缺少这些位置间移动数据的支撑,任何路径优化算法都将失去计算基础。

位置(Locations)定义

在 VROOM 中,位置代表地图上对路径规划有重要意义的地理节点,包括:

  • 运输工具的起始/终止位置
  • 任务执行位置

通过 JSON 输入的坐标定义示例:

json 复制代码
{
  "vehicles": [
    {
      "id": 1,
      "start": [2.3522, 48.8566], // 车辆1起始位置(巴黎仓库)
      "end": [2.3522, 48.8566],   // 车辆1终止位置
      "capacity": [100],
      "profile": "car"
    }
  ],
  "jobs": [
    {
      "id": 10,
      "location": [2.2945, 48.8584], // 任务10位置(埃菲尔铁塔)
      "service": 300,
      "delivery": [10]
    },
    {
      "id": 20,
      "location": [2.3490, 48.8641], // 任务20位置(卢浮宫)
      "service": 180,
      "delivery": [20]
    }
  ]
}

该配置包含三个物理位置:

  1. 仓库坐标(2.3522, 48.8566)
  2. 任务10坐标(2.2945, 48.8584)
  3. 任务20坐标(2.3490, 48.8641)

VROOM 通过内部索引机制管理位置唯一性,相同坐标自动归并为同一位置。若使用预计算矩阵,可直接指定位置索引:

json 复制代码
{
  "vehicles": [
    { "id": 1, "start": 0, "end": 0, "profile": "car" } // 索引0表示仓库
  ],
  "jobs": [
    { "id": 10, "location": 1, "service": 300 },  // 索引1对应任务10
    { "id": 20, "location": 2, "service": 180 }   // 索引2对应任务20
  ],
  "matrices": {
    // 矩阵数据需与索引0/1/2对应
  }
}

内部 vroom::Location 结构体实现:

cpp 复制代码
// 简化版位置结构体(src/structures/vroom/location.h)
class Location {
private:
  Index _index;            // 内部自动分配的索引
  OptionalCoordinates _coords; // 可选地理坐标
  bool _user_index;        // 是否为用户定义索引

public:
  explicit Location(Index index);  // 用户索引构造器
  Location(const Coordinates& coords); // 坐标构造器
  // 获取索引/坐标等方法...
};

该结构支持坐标预定义索引两种定位方式的无缝切换。

矩阵(Matrices)

矩阵是存储位置间移动成本的方阵数据结构,主要类型包括:

  1. 耗时矩阵(Duration):存储位置间移动秒数
  2. 距离矩阵(Distance):存储位置间移动米数
  3. 成本矩阵(Cost):自定义成本指标

对于 N 个唯一位置,矩阵为 N×N 结构。矩阵元素 [i][j] 表示从索引 i 位置到索引 j 位置的移动成本。

矩阵数据在 JSON 中的配置示例:

json 复制代码
{
  "matrices": {
    "car": {
      "durations": [
        [0, 600, 900],    // 仓库(0)到各点耗时
        [580, 0, 300],    // 任务10(1)到各点耗时
        [880, 320, 0]     // 任务20(2)到各点耗时
      ],
      "distances": [
        [0, 5000, 7000],  // 仓库(0)到各点距离
        [4800, 0, 2500],  // 任务10(1)到各点距离
        [6800, 2700, 0]   // 任务20(2)到各点距离
      ]
    }
  }
}

矩阵特性说明:

  • 非对称性:A→B 与 B→A 的耗时/距离可能不同(受单行道等因素影响)
  • 索引强关联:用户定义索引必须与矩阵行列顺序严格对应

内部矩阵存储采用一维向量优化访问效率:

cpp 复制代码
template <class T> class Matrix {
  std::size_t n;          // 矩阵维度
  std::vector<T> data;    // 矩阵元素线性存储

public:
  T* operator[](std::size_t i) { 
    return data.data() + (i * n); // 模拟二维访问
  }
  // 其他方法...
};

数据处理全流程

VROOM 通过 vroom::io::parse 解析输入数据时执行以下关键步骤:

成本封装器(CostWrapper)是核心访问接口:

cpp 复制代码
// 简化版成本访问逻辑
const auto& cost_wrapper = input.get_cost_wrapper(vehicle.profile);
Duration 耗时 = cost_wrapper.duration(起点索引, 终点索引);
Distance 距离 = cost_wrapper.distance(起点索引, 终点索引); 

应用场景推演

以仓库(0)→任务10(1)→任务20(2)→仓库(0)的路线为例:

plaintext 复制代码
移动段       耗时(s)   距离(m)
0→1        600      5000
1→2        300      2500  
2→0        880      6800
----------------------------
总计       1780     14300

VROOM 在优化过程中通过矩阵查询累计各路径成本,结合服务时间、时间窗等约束寻找全局最优解。

总结

位置与矩阵构成了移动成本计算的基础层。

通过精确配置位置关系与移动成本矩阵,或依赖路由引擎动态生成(详见第四章:路由集成),VROOM 得以构建完整的成本评估体系。

理解此章内容将为后续学习路由集成机制奠定重要基础。


第四章:路由集成

在前几章中,我们学习了如何定义路径规划问题的核心要素:

需要执行的任务(第二章:任务与运输工具)以及任务执行位置运输工具的起止点(第三章:位置与矩阵)。

我们了解到,获取位置间的移动耗时/距离数据对路径优化至关重要,这些信息存储在矩阵中。

但当用户仅拥有坐标数据而缺乏预计算矩阵时,VROOM 如何获取真实道路网络的移动参数?

这正是路由集成机制的核心价值。

连接现实世界的桥梁

路由集成是 VROOM 与专业地图服务交互的智能通道。不同于简单的直线距离计算,VROOM 通过集成以下主流路由引擎获取真实道路数据:

  • OSRM(开源路由引擎)
  • Openrouteservice (ORS)
  • Valhalla

当用户在 JSON 输入中指定车辆配置(如"car")并提供地理坐标时,VROOM 将自动通过路由集成模块完成以下流程:

  1. 数据收集汇总特定配置(如汽车)关联的所有坐标点
  2. 请求构建生成路由引擎可识别的矩阵查询请求
  3. 服务交互 :通过 HTTP 协议发送请求至路由服务
  4. 结果解析提取响应中的矩阵数据并转换为 VROOM 标准格式
  5. 路径可视化:在求解完成后获取道路级路径坐标串(用于地图展示)

路由服务配置机制

用户通过命令行参数指定路由引擎类型与服务地址,而非 JSON 输入。典型启动命令示例:

bash 复制代码
vroom --router osrm -m http://localhost:5000 < 输入文件.json

参数解读:

  • --router osrm:选择 OSRM 引擎
  • -m http://localhost:5000:路由服务地址
  • 输入文件.json:包含坐标与配置的输入文件

输入文件示例:

json 复制代码
{
  "vehicles": [
    {
      "id": 1,
      "start": [2.3522, 48.8566],  // 巴黎仓库坐标
      "end": [2.3522, 48.8566],
      "capacity": [100],
      "profile": "car"  // 汽车配置方案
    }
  ],
  "jobs": [
    {
      "id": 10,
      "location": [2.2945, 48.8584],  // 埃菲尔铁塔坐标
      "service": 300,
      "delivery": [10]
    }
  ]
}

内部实现架构

VROOM 通过抽象化的路由封装器(Wrapper)实现多引擎支持,其核心类结构如下:

基础封装器接口

cpp 复制代码
class Wrapper {
public:
  std::string profile;  // 支持的配置方案

  // 矩阵数据获取接口
  virtual Matrices get_matrices(const vector<Location>& locs) = 0;

  // 路径几何数据获取接口
  virtual void add_geometry(Route& route) = 0;
};

前文传送:[xiaozhi-esp32] 构建智能AI设备 | 开发板抽象层 | 通信协议层

(这个助手兼容多种硬件的架构设计,不同的硬件抽象为了统一的驱动,参考VFS的思想)

HTTP 通信基类

cpp 复制代码
class HttpWrapper : public Wrapper {
protected:
  Server _server;  // 服务端配置

  // 构建服务特定查询
  virtual string build_query(...) = 0;

  // 执行HTTP请求
  string run_query(const string& query) {
    // 实现HTTPS请求发送与接收
  }
};

具体引擎封装器(如OsrmRoutedWrapper)继承自HttpWrapper,实现服务特定的查询构建与结果解析逻辑。

数据处理全流程

相当于是借助第三方库的力量

应用场景

以包含仓库与两个配送点的汽车路径问题为例:

  1. 矩阵获取阶段

    • 封装器发送三个坐标点的矩阵查询至 OSRM
    • 接收包含 3x3 耗时/距离矩阵的 JSON 响应
    • 转换为vroom::Matrices对象供优化器使用
  2. 路径优化阶段

    • 求解器通过CostWrapper获取移动成本
    • 生成最优路径序列(如仓库→任务A→任务B→仓库)
  3. 几何数据获取

    • 对最终路径发送路线查询请求
    • 解析响应中的 GeoJSON 路径坐标串
    • 写入解决方案供地图可视化使用

总结

路由集成机制使 VROOM 具备以下核心能力:

  1. 现实道路建模:考虑单行道、限速等实际路况
  2. 多运输模式支持:通过不同配置方案实现汽车/卡车/自行车等差异计算
  3. 动态数据更新:实时获取最新路况信息(需路由引擎支持)
  4. 可视化增强:提供导航级路径细节展示

通过解耦路由服务优化引擎,VROOM 保持了架构的扩展性,可快速接入新型路由引擎。这种设计模式为处理复杂的物流路径问题提供了坚实基础。

在掌握路由集成机制后,我们将进入更具挑战性的约束条件处理环节:第五章:时间窗约束将解析如何在路径优化中纳入时效性要求。

相关推荐
在努力的韩小豪6 分钟前
如何从0开始构建自己的第一个AI应用?(Prompt工程、Agent自定义、Tuning)
人工智能·python·llm·prompt·agent·ai应用·mcp
云卓SKYDROID6 分钟前
无人机环境感知系统运行与技术难点!
人工智能·计算机视觉·目标跟踪·无人机·科普·高科技·云卓科技
悠哉清闲22 分钟前
C++ MediaCodec H264解码
开发语言·c++
网安INF24 分钟前
深度学习中的 Seq2Seq 模型与注意力机制
人工智能·深度学习·神经网络·注意力机制·seq2seq
火山引擎开发者社区1 小时前
ByteBrain x 清华 VLDB25|时序多模态大语言模型 ChatTS
人工智能·语言模型·自然语言处理
thusloop1 小时前
380. O(1) 时间插入、删除和获取随机元素
数据结构·算法·leetcode
SoaringPigeon1 小时前
从深度学习的角度看自动驾驶
人工智能·深度学习·自动驾驶
产品经理独孤虾1 小时前
如何利用AI大模型对已有创意进行评估,打造杀手级的广告创意
人工智能·大模型·aigc·产品经理·数字营销·智能营销·智能创意生成
MobotStone1 小时前
无代码+AI时代,为什么你仍然需要像个开发者一样思考
人工智能·算法
緈福的街口2 小时前
【leetcode】584. 寻找用户推荐人
算法·leetcode·职场和发展