找回密码
 立即注册
查看: 895|回复: 5

[技术探讨] 解决traccar高德地图漂移的另一种办法

[复制链接]

2

主题

18

回帖

172

积分

注册会员

积分
172
金钱
152
HASS币
0
发表于 2024-10-10 11:09:24 | 显示全部楼层 |阅读模式
不赘述其他问题,解决漂移有很多种办法,可以查询到的一种是通过第三方脚本定时的读取数据库并进行修改,另一种方法是修改app在收到gps信号之后就修改,不过这两种不便捷这里推荐一种数据库触发器的方式进行修复漂移,前提是用postgresql,然后安装pg-coordtransform和postgis扩展,扩展安装办法自己百度,很简单,之后数据库中就具备了一个函数geoc_wgs84togcj02,这就是我们用来把gps经纬度转换到火星坐标。
首先把tc_positions表扩展两个列:latitude_gps和longitude_gps用于记录gps上传的经纬度,也方便以后进行其他处理使用。
之后就是先创建触发器函数
CREATE OR REPLACE FUNCTION wgs84_to_gcj02()
RETURNS TRIGGER AS $$
DECLARE
    geom_point GEOMETRY(Point, 4326);
    converted_geom GEOMETRY;
    orig_longitude DOUBLE PRECISION;
    orig_latitude DOUBLE PRECISION;
BEGIN
    orig_longitude := NEW.longitude;
    orig_latitude := NEW.latitude;
    geom_point := ST_SetSRID(ST_MakePoint(NEW.longitude, NEW.latitude), 4326);
    converted_geom := geoc_wgs84togcj02(geom_point);
    NEW.longitude := ST_X(converted_geom);
    NEW.latitude := ST_Y(converted_geom);
    NEW.latitude_gps := orig_latitude;
    NEW.longitude_gps := orig_longitude;
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

然后创建触发器和tc_positions表绑定
CREATE TRIGGER wgs84_to_gcj02_trigger
BEFORE INSERT ON tc_positions
FOR EACH ROW
EXECUTE PROCEDURE wgs84_to_gcj02();


这样每次插入gps经纬度就会先进行转换,如此就可以了,我觉得这个方案更便捷
回复

使用道具 举报

15

主题

470

回帖

2668

积分

金牌会员

积分
2668
金钱
2183
HASS币
0
发表于 2024-10-10 11:13:25 | 显示全部楼层
看懂了不会弄,直接出个镜像
回复

使用道具 举报

1

主题

175

回帖

2284

积分

金牌会员

积分
2284
金钱
2108
HASS币
0
发表于 2024-10-11 14:10:06 | 显示全部楼层
这个方法好,不知道有没有mysql数据库的
回复

使用道具 举报

0

主题

21

回帖

119

积分

注册会员

积分
119
金钱
98
HASS币
0
发表于 2024-10-11 14:31:25 | 显示全部楼层
其实可以直接编译traccar的服务端程序,在服务端接收到客户端GPS报文是修改坐标偏移问题
回复

使用道具 举报

2

主题

18

回帖

172

积分

注册会员

积分
172
金钱
152
HASS币
0
 楼主| 发表于 2024-10-11 14:43:03 | 显示全部楼层
TangKii 发表于 2024-10-11 14:31
其实可以直接编译traccar的服务端程序,在服务端接收到客户端GPS报文是修改坐标偏移问题 ...

是,不过如果作者更新就得再修改,要么试着提交到社区
回复

使用道具 举报

39

主题

263

回帖

2241

积分

金牌会员

积分
2241
金钱
1939
HASS币
0
发表于 2025-2-16 21:10:44 | 显示全部楼层
MattSmell 发表于 2024-10-11 14:10
这个方法好,不知道有没有mysql数据库的

GPT给的mysql的方法

添加列
ALTER TABLE tc_positions
ADD COLUMN latitude_gps DOUBLE NULL AFTER latitude,
ADD COLUMN longitude_gps DOUBLE NULL AFTER longitude;

自定义函数
CREATE FUNCTION geoc_wgs84togcj02(geom POINT)
RETURNS POINT
DETERMINISTIC
BEGIN
    DECLARE lon DOUBLE;
    DECLARE lat DOUBLE;
    DECLARE gcj_lon DOUBLE;
    DECLARE gcj_lat DOUBLE;
    SET lon = ST_X(geom);
    SET lat = ST_Y(geom);

    -- 在此处实现 WGS84 -> GCJ-02 的具体数学转换
    -- 这里只是演示,用了一个简单的偏移,实际需要完整公式
    SET gcj_lon = lon + 0.002;
    SET gcj_lat = lat + 0.0018;

    RETURN ST_GeomFromText(CONCAT('POINT(', gcj_lon, ' ', gcj_lat, ')'), 4326);
END;

创建触发器,自动转换
DELIMITER //

CREATE TRIGGER wgs84_to_gcj02_trigger
BEFORE INSERT ON tc_positions
FOR EACH ROW
BEGIN
    DECLARE orig_longitude DOUBLE;
    DECLARE orig_latitude DOUBLE;
    DECLARE geom_point GEOMETRY;
    DECLARE converted_geom GEOMETRY;
   
    -- 1) 先保存原始 WGS84 坐标
    SET orig_longitude = NEW.longitude;
    SET orig_latitude  = NEW.latitude;
   
    -- 2) 构造一个 SRID=4326 的 POINT 对象
    SET geom_point = ST_GeomFromText(
        CONCAT('POINT(', orig_longitude, ' ', orig_latitude, ')'),
        4326
    );
   
    -- 3) 调用自定义函数,将 WGS84 -> GCJ-02
    SET converted_geom = geoc_wgs84togcj02(geom_point);
   
    -- 4) 更新触发器中的 NEW 行
    --    4.1) 将转换后的 GCJ-02 坐标写入 longitude、latitude
    SET NEW.longitude = ST_X(converted_geom);
    SET NEW.latitude  = ST_Y(converted_geom);
   
    --    4.2) 将原始坐标存入 latitude_gps、longitude_gps
    SET NEW.longitude_gps = orig_longitude;
    SET NEW.latitude_gps  = orig_latitude;
END;
//

DELIMITER ;

观察了下 latitude_gps 和 longitude_gps 是转换后的坐标了


回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|Hassbian

GMT+8, 2025-5-4 21:26 , Processed in 0.489968 second(s), 23 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表