背景
因为GPS设备和网络的原因,采集到的位置信息会出现各种异常情况,包括但不限于
- 设备掉线,导致相邻的两个点之间有很大的时间差和距离(跳跃点)。
- 设备异常,导致在连续的时间戳下,GPS点位置有突然很大偏差(漂移点)。
- 设备异常,导致相同时间戳下,返回多条数据(重复数据)。
结合我们的业务场景,我们可以粗略的认为
- 通过简单的按时间戳去重算法,很容易去掉重复数据。
- 在可以接受的时间范围内,可以容忍数据中断造成的跳跃点(或者通过拟合算法来模拟缺失数据)。
- 漂移点会对后续分析造成很大的影响,不能接受明显地漂移(比如跨地区这种光速漂移)。
在数据预处理过程中,我们需要排除掉漂移点数据,严谨的算法有
- 滑动窗口过滤法(中值,均值);
- 卡尔曼滤波法;
- 粒子滤波法;
速度推算法
算法描述和代码
结合具体业务场景(普通小型车辆速度必须在180KM/H以内,重卡速度在100以内),我们这里使用一个简单的算法,基于推算速度进行过滤。思路如下
- 假设一段时间内,车辆的速度满足正态分布;
- 按时间序列对GPS点进行排序;
- 通过相邻两个GPS点之间的时间差和距离差,推算出当前GPS点的速度。
- 因为存在缺失点,漂移点等情况,所以推算速度和实际速度并不一样;
- 推算速度大于50米/秒(即180KM/H)的数据,疑是漂移点;
- 从轨迹序列中去除漂移点;
注意: 这个算法假设正态分布,并预设最大速度阈值,所以结果并不严谨。
alter table demo.t_taxi_trajectory add column traj_clean geometry(linestringm, 4326);
/* 基于推算速度判断异常轨迹点,清除异常点后返回新的轨迹。 @traj 轨迹 @mps_max 用米/秒作为单位的速度阈值 */
create or replace function f_get_clean_trajectory(traj geometry, mps_max int=50)
returns geometry
as ?
declare
traj_clean geometry;
pt geometry;
p0 geometry=null;
dur_meters float=0;
dur_seconds int=0;
begin
for pt in select (st_dumppoints(traj)).geom loop
-- 1st point
if p0 is null then
p0 := pt;
traj_clean := st_makeline(pt);
-- other points
else
dur_meters := st_distance(pt::geography, p0::geography);
dur_seconds := st_m(pt) - st_m(p0);
-- 根据相邻两点的距离和时间,推算当前点的速度。推算速度小于阈值,就认为是正常GPS点
if ( dur_meters / dur_seconds ) <= mps_max then
--raise notice '% - % - %', dur_meters, dur_seconds, ( dur_meters / dur_seconds );
traj_clean := st_addpoint(traj_clean, pt);
p0 := pt;
else
--raise notice '% - % - %', dur_meters, dur_seconds, ( dur_meters / dur_seconds );
null;
end if;
end if;
end loop;
return traj_clean;
end;
? language plpgsql strict;
算法测试
通过观察清洗前后的轨迹图形,人肉评估一下算法的效果。因为样本数据是北京出租车轨迹,在城市内出租车时速不会超过120KM/H,所以我们设置阈值30M/S。
-- 增加一个清洗后轨迹字段
alter table demo.t_taxi_trajectory add column traj_clean geometry;
update demo.t_taxi_trajectory
set traj_clean = demo.f_get_clean_trajectory(traj,30)
where traj_clean is null
;
还原轨迹点,并在QGIS展现
-- 还原轨迹点
with dump_pt as
(
select
tid, dt,
--(st_dumppoints(tr.traj)) as dpt -- 原始轨迹
(st_dumppoints(tr.traj_clean)) as dpt -- 清洗后轨迹
from demo.t_taxi_trajectory tr
where tr.tid = 1353 and tr.dt = '2008-02-03'
),
--
pt_list as
(
select
(dpt).path[1] as rn,
(dpt).geom as pt ,
*
from dump_pt
)
--
select
tid, dt, rn,
to_timestamp(st_m(pt)) as ts,
st_distance(pt::geography, (lag(pt) over w)::geography)::int as len_m ,
to_timestamp(st_m(pt)) - (lag(to_timestamp(st_m(pt))) over w) as dur,
pt,
1 as endflag
from pt_list
window w as (partition by tid order by dt)
order by tid, ts
;
目测效果-漂移点
效果图如上,红色实线是原始轨迹,蓝色虚线是清洗轨迹。对比可见
- 正常点的轮廓完全重合,说明整体并没有变形;
- A点,是明显的漂移点,被清除掉了;
- B点,不是漂移点,但是轨迹有明显的跳跃,应该是B点附近出现了较长时间缺失点。
目测效果-缺失点
进一步观察,B点序号是913,我们来验证913附近是否出现了长时间缺失点。
rn | ts | len_m | dur
-----+------------------------+-------+----------
910 | 2008-02-03 20:25:28+08 | 67 | 00:04:28
911 | 2008-02-03 20:28:55+08 | 2 | 00:03:27
912 | 2008-02-03 20:29:36+08 | 355 | 00:00:41
913 | 2008-02-03 20:46:53+08 | 5945 | 00:17:17
914 | 2008-02-03 20:58:17+08 | 12019 | 00:11:24
915 | 2008-02-03 21:02:01+08 | 1636 | 00:03:44
916 | 2008-02-03 21:02:06+08 | 20 | 00:00:05
从查询结果来看
- 轨迹点的正常采集时间间隔应该在3分钟之内;
- 点913,914出现了明显地时间间隔(17分钟,11分钟);
- 验证了有长时间缺失点的设想;
延展思考: 如果是严格的应用场景,可以在跳跃点附近对这一段轨迹进行拆分,形成连续的多段轨迹数据。
今天的文章PostGIS_小白笔记_清洗轨迹漂移点分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/21407.html