快速入门

本文帮助您快速理解Ganos MapMatching引擎的基本用法,包括扩展创建、创建路网数据、构建拓扑网络图、执行轨迹匹配等部分。

基本概念

  • 路网(Road Network):指描述道路交通网络结构和特性的数字化信息集合,包括了道路的位置、类型、等级、连接关系、几何形状、交通规则等多方面的信息。

  • 节点(Node):在路网数据中,节点通常代表道路的交叉点或端点,是道路网络中连接各边的点。

  • 边(Edge):在路网数据的上下文中,边是路网中连接两个节点的抽象概念。边主要用来表示两个地点之间的连接关系,而不涉及具体的道路物理特征。在无向图中,边没有方向;在有向图中,边则可以表示行驶方向。边通常会携带一些属性信息,比如长度、是否可通行等,但其核心作用是构建路网的结构框架。

  • 路段(Segment):路段是道路的一部分,具有实际的物理属性和地理位置信息,它是路网中连续的一段道路,可能从一个路口开始到下一个路口结束,或者是道路中具有相同特征(如车道数、限速等)的一段。路段数据比边更为详细,通常包含路面材质、宽度、坡度、车道配置、交通标志信息、路权(如是否允许转弯、直行等)等。路段是实现导航、交通分析、道路维护规划等应用的基础单位。

案例参考

创建插件

使用MapMatching函数需要您在数据库中创建ganos_mapmatching插件。

CREATE EXTENSION ganos_mapmatching CASCADE;
CREATE EXTENSION ganos_fdw CASCADE;
说明
  • 创建ganos_mapmatching插件时,将同步安装ganos_geometryganos_spatialrefganos_trajectory插件,如遇到类似ERROR: invalid extension name: "ganos_trajectory"报错,请联系我们处理。

  • 为避免权限问题,建议您将扩展安装在public模式下。

    CREATE EXTENSION ganos_mapmatching WITH SCHEMA PUBLIC CASCADE;
    CREATE EXTENSION ganos_fdw WITH SCHEMA PUBLIC CASCADE;

示例一:利用自有路网数据实现道路匹配。

  1. 导入路网数据。

    CREATE TABLE network (fid bigint,   -- 路段的唯一标识
                             source bigint,  -- 路段的开始节点标识
                             target bigint,  -- 路段的结束节点标识
                             cost double precision, -- 道路权重值(目前未使用)
                             geom public.geometry(LineString,4326) --路段的几何对象
    );
    
    INSERT INTO network(fid, source, target, cost, geom)
    VALUES(1, 1, 2,1, st_geomfromtext('LINESTRING(2 1,2 0)'));
    INSERT INTO network(fid, source, target, cost, geom)
    VALUES(2, 2, 1,1, st_geomfromtext('LINESTRING(2 0,2 1)'));
    INSERT INTO network(fid, source, target, cost, geom)
    VALUES(3, 3, 1,1, st_geomfromtext('LINESTRING(3 1,2 1)'));
    INSERT INTO network(fid, source, target, cost, geom)
    VALUES(4, 4, 3,1, st_geomfromtext('LINESTRING(4 1,3 1)'));
    INSERT INTO network(fid, source, target, cost, geom)
    VALUES(5, 1, 5,1, st_geomfromtext('LINESTRING(2 1,2 2)'));
    INSERT INTO network(fid, source, target, cost, geom)
    VALUES(6, 5, 1,1, st_geomfromtext('LINESTRING(2 2,2 1)'));
    INSERT INTO network(fid, source, target, cost, geom)
    VALUES(7, 3, 6,1, st_geomfromtext('LINESTRING(3 1,3 2)'));
    INSERT INTO network(fid, source, target, cost, geom)
    VALUES(8, 7, 8,1, st_geomfromtext('LINESTRING(0 2,1 2)'));
    INSERT INTO network(fid, source, target, cost, geom)
    VALUES(9, 8, 7,1, st_geomfromtext('LINESTRING(1 2,0 2)'));
    INSERT INTO network(fid, source, target, cost, geom)
    VALUES(10,5, 8,3, st_geomfromtext('LINESTRING(2 2,1 2)'));
    INSERT INTO network(fid, source, target, cost, geom)
    VALUES(11,8, 5,3, st_geomfromtext('LINESTRING(1 2,2 2)'));
    INSERT INTO network(fid, source, target, cost, geom)
    VALUES(12,6, 5,1, st_geomfromtext('LINESTRING(3 2,2 2)'));
    INSERT INTO network(fid, source, target, cost, geom)
    VALUES(13,5, 6,1, st_geomfromtext('LINESTRING(2 2,3 2)'));
    INSERT INTO network(fid, source, target, cost, geom)
    VALUES(14,6, 9,1, st_geomfromtext('LINESTRING(3 2,4 2)'));
    INSERT INTO network(fid, source, target, cost, geom)
    VALUES(15,9, 6,1, st_geomfromtext('LINESTRING(4 2,3 2)'));
    INSERT INTO network(fid, source, target, cost, geom)
    VALUES(16,10,5,1, st_geomfromtext('LINESTRING(2 3,2 2)'));
    INSERT INTO network(fid, source, target, cost, geom)
    VALUES(17,5, 10,1, st_geomfromtext('LINESTRING(2 2,2 3)'));
    INSERT INTO network(fid, source, target, cost, geom)
    VALUES(18,6, 11,1, st_geomfromtext('LINESTRING(3 2,3 3)'));
    INSERT INTO network(fid, source, target, cost, geom)
    VALUES(19,10,11,1, st_geomfromtext('LINESTRING(2 3,3 3)'));
    INSERT INTO network(fid, source, target, cost, geom)
    VALUES(20,11,12,1, st_geomfromtext('LINESTRING(3 3,4 3)'));
    INSERT INTO network(fid, source, target, cost, geom)
    VALUES(21,13,10,1, st_geomfromtext('LINESTRING(2 4,2 3)'));
    INSERT INTO network(fid, source, target, cost, geom)
    VALUES(22,10,13,1, st_geomfromtext('LINESTRING(2 3,2 4)'));
    INSERT INTO network(fid, source, target, cost, geom)
    VALUES(23,9, 12,1, st_geomfromtext('LINESTRING(4 2,4 3)'));
    INSERT INTO network(fid, source, target, cost, geom)
    VALUES(24,12,9,1, st_geomfromtext('LINESTRING(4 3,4 2)'));
    INSERT INTO network(fid, source, target, cost, geom)
    VALUES(25,9, 4,1, st_geomfromtext('LINESTRING(4 2,4 1)'));
    INSERT INTO network(fid, source, target, cost, geom)
    VALUES(26,4, 9,1, st_geomfromtext('LINESTRING(4 1,4 2)'));
    INSERT INTO network(fid, source, target, cost, geom)
    VALUES(27,14,15,1, st_geomfromtext('LINESTRING(0.5 3.5,2 3.5)'));
    INSERT INTO network(fid, source, target, cost, geom)
    VALUES(28,15,14,1, st_geomfromtext('LINESTRING(2 3.5,0.5 3.5)'));
    INSERT INTO network(fid, source, target, cost, geom)
    VALUES(29,16,17,1, st_geomfromtext('LINESTRING(3.5 4,3.5 2.3)'));
    INSERT INTO network(fid, source, target, cost, geom)
    VALUES(30,17,16,1, st_geomfromtext('LINESTRING(3.5 2.3,3.5 4)'));

    image

  2. 构建地图匹配工作空间。

    SELECT st_createworkspace('mm_ws_test1', 'select fid, source, target, geom from network');

    工作空间中生成的路网结构如下:

    image

  3. 创建待匹配的轨迹线数据。

    CREATE TABLE traj(id int, geom geometry(linestring, 4326));
    INSERT INTO traj(id, geom)
    VALUES(1,st_geomfromtext('LINESTRING(4.15 1.6,3.47 0.92,2.4 0.92,2.14 1.53,2.14 2.57,2.49 2.98)'));

    image

  4. 执行道路匹配。

    SELECT st_astext(st_mapmatching('mm_ws_test1', geom, '{"algorithm":"stmatch","k":4,"r":0.25,"e":0.5}'::text)) AS geom
    FROM traj;

    返回结果如下:

                         geom                     
    ----------------------------------------------
     LINESTRING(4 1.6,4 1,3 1,2 1,2 2,2 3,2.49 3)
    (1 row)

    image

示例二:利用OSM数据实现道路匹配。

  1. 导入OSM数据

    -- 导入OSS上的OSM路网数据,目前只支持导入OSS上的源文件
    -- accesskeyid,accesskeysecret为OSS的访问密钥
    -- directory指文件夹,如果在根目录下可不填
    SELECT st_regforeigntables('OSS://{accesskeyid}:{accesskeysecret}@{endpoint}/{bucket}/{directory}/macau-latest.osm.pbf' , 'osmserver', 'OSMNT');
    SELECT st_setcplconfig('OSS_ENDPOINT', '{endpoint}');
    
    -- 提取路网节点数据
    CREATE TABLE macau_network_nodes
    (
        id     BIGSERIAL,
        fid    BIGINT,
        eout   INTEGER,
        lon    DOUBLE PRECISION ,
        lat    DOUBLE PRECISION,
        cnt    INTEGER,
        chk    INTEGER,
        ein    INTEGER,
        name   text,
        tags   text,
        point  GEOMETRY(point, 4326)
    );
    
    INSERT INTO macau_network_nodes(fid, lon, lat, name, tags, point)
    SELECT osm_id::bigint, ST_X(geom), ST_Y(geom), name, to_json(other_tags)::jsonb, geom
    FROM points;
    
    -- 提取路网边数据
    CREATE TABLE macau_network_ways
    (
        gid               BIGSERIAL,
        fid            BIGINT,
        length            DOUBLE PRECISION,
        length_m          DOUBLE PRECISION,
        p                 TEXT,
        source            BIGINT,
        target            BIGINT,
        source_osm        BIGINT,
        target_osm        BIGINT,
        cost              DOUBLE PRECISION,
        reverse_cost      DOUBLE PRECISION DEFAULT -1,
        cost_s            DOUBLE PRECISION,
        reverse_cost_s    DOUBLE PRECISION DEFAULT -1,
        rule              TEXT,
        one_way           INT,
        oneway            TEXT,
        x1                DOUBLE PRECISION,
        y1                DOUBLE PRECISION,
        x2                DOUBLE PRECISION,
        y2                DOUBLE PRECISION,
        maxspeed_forward  DOUBLE PRECISION,
        maxspeed_backward DOUBLE PRECISION DEFAULT -1,
        priority          DOUBLE PRECISION DEFAULT 1,
        name              TEXT,
        tags              JSONB,
        linestring        GEOMETRY(LINESTRING, 4326)
    );
    
    INSERT INTO macau_network_ways(fid, source_osm, target_osm, name, tags, linestring)
    SELECT osm_id::bigint, source_osm, target_osm, name, to_json(other_tags)::jsonb, geom
    FROM lines;
  2. 构造路网数据。

    -- 更新路网起止节点ID
    UPDATE macau_network_ways
    SET source = macau_network_nodes.id
    FROM macau_network_nodes
    WHERE macau_network_ways.source_osm = macau_network_nodes.fid;
    
    UPDATE macau_network_ways
    SET target = macau_network_nodes.id
    FROM macau_network_nodes
    WHERE macau_network_ways.target_osm = macau_network_nodes.fid;

    image

  3. 构建地图匹配工作空间。

    SELECT st_createworkspace('mm_ws_test2', 'select fid, source, target, linestring from macau_network_ways');
  4. 执行道路匹配。

    SELECT st_astext(st_mapmatching('mm_ws_test2', 'LINESTRING(113.5492 22.1881,113.5493 22.1881,113.5504 22.1885,113.5505 22.1886,113.5502 22.189,113.5501 22.1891,113.5491 22.1887,113.5489 22.1887)', '{"algorithm":"stmatch","k":4,"r":0.25,"e":0.5,"tolerance":0.5,"vmax":1.0,"factor":0.5}'::text));

    返回结果如下:

    LINESTRING(113.5492633 22.1880942,113.5493491 22.1881266,113.5504129 22.1885289,113.5505378 22.1885762,113.5502504 22.1892274,113.5505378 22.1885762,113.5502504 22.1892274,113.5501282 22.1891812,113.5490843 22.1887864,113.5489761 22.1887455)

    image