path_smooth_tool.dart 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. import 'dart:core';
  2. import 'dart:math';
  3. import 'package:amap_flutter_base/amap_flutter_base.dart';
  4. class PathSmoothTool {
  5. int mIntensity = 3;
  6. double mThreshhold = 0.3;
  7. double mNoiseThreshhold = 10;
  8. // PathSmoothTool({this.mIntensity = 3, this.mThreshhold = 0.3, this.mNoiseThreshhold = 10});
  9. /**
  10. * 轨迹平滑优化
  11. * @param originlist 原始轨迹list,list.size大于2
  12. * @return 优化后轨迹list
  13. */
  14. List<LatLng>? pathOptimize(List<LatLng> originlist) {
  15. List<LatLng>? list = removeNoisePoint(originlist); //去噪
  16. List<LatLng> afterList = kalmanFilterPath(list, mIntensity); //滤波
  17. List<LatLng>? pathoptimizeList = reducerVerticalThreshold(afterList, mThreshhold); //抽稀
  18. // Log.i("MY","originlist: "+originlist.length);
  19. // Log.i("MY","list: "+list.length);
  20. // Log.i("MY","afterList: "+afterList.length);
  21. // Log.i("MY","pathoptimizeList: "+pathoptimizeList.length);
  22. return pathoptimizeList;
  23. }
  24. /**
  25. * 轨迹去噪,删除垂距大于20m的点
  26. * @param originlist 原始轨迹list,list.size大于2
  27. * @return
  28. */
  29. List<LatLng>? removeNoisePoint(List<LatLng> originlist) {
  30. return reduceNoisePoint(originlist, mNoiseThreshhold);
  31. }
  32. /********************************************************************************************************/
  33. /**
  34. * 轨迹线路滤波
  35. * @param originlist 原始轨迹list,list.size大于2
  36. * @param intensity 滤波强度(1—5)
  37. * @return
  38. */
  39. List<LatLng> kalmanFilterPath(List<LatLng>? originlist, int intensity) {
  40. List<LatLng> kalmanFilterList = [];
  41. if (originlist == null || originlist.length <= 2) return kalmanFilterList;
  42. initial(); //初始化滤波参数
  43. LatLng? latLng;
  44. LatLng lastLoc = originlist[0];
  45. kalmanFilterList.add(lastLoc);
  46. for (int i = 1; i < originlist.length; i++) {
  47. LatLng curLoc = originlist[i];
  48. latLng = kalmanFilterPoint(lastLoc, curLoc, intensity);
  49. if (latLng != null) {
  50. kalmanFilterList.add(latLng);
  51. lastLoc = latLng;
  52. }
  53. }
  54. return kalmanFilterList;
  55. }
  56. /**
  57. * 单点滤波
  58. * @param lastLoc 上次定位点坐标
  59. * @param curLoc 本次定位点坐标
  60. * @param intensity 滤波强度(1—5)
  61. * @return 滤波后本次定位点坐标值
  62. */
  63. LatLng? kalmanFilterPoint(LatLng? lastLoc, LatLng? curLoc, int intensity) {
  64. if (pdelt_x == null || pdelt_y == null) {
  65. initial();
  66. }
  67. LatLng? kalmanLatlng;
  68. if (lastLoc == null || curLoc == null) {
  69. return curLoc;
  70. }
  71. int _intensity = intensity;
  72. if (intensity < 1) {
  73. _intensity = 1;
  74. } else if (intensity > 10) {
  75. _intensity = 10;
  76. }
  77. for (int j = 0; j < _intensity; j++) {
  78. kalmanLatlng = kalmanFilter(lastLoc.longitude, curLoc!.longitude, lastLoc.latitude, curLoc.latitude);
  79. curLoc = kalmanLatlng;
  80. }
  81. return kalmanLatlng;
  82. }
  83. /***************************卡尔曼滤波开始********************************/
  84. late double lastLocation_x; //上次位置
  85. late double currentLocation_x; //这次位置
  86. late double lastLocation_y; //上次位置
  87. late double currentLocation_y; //这次位置
  88. late double estimate_x; //修正后数据
  89. late double estimate_y; //修正后数据
  90. double? pdelt_x; //自预估偏差
  91. double? pdelt_y; //自预估偏差
  92. late double mdelt_x; //上次模型偏差
  93. late double mdelt_y; //上次模型偏差
  94. late double gauss_x; //高斯噪音偏差
  95. late double gauss_y; //高斯噪音偏差
  96. late double kalmanGain_x; //卡尔曼增益
  97. late double kalmanGain_y; //卡尔曼增益
  98. double m_R = 0;
  99. double m_Q = 0;
  100. //初始模型
  101. void initial() {
  102. pdelt_x = 0.001;
  103. pdelt_y = 0.001;
  104. // mdelt_x = 0;
  105. // mdelt_y = 0;
  106. mdelt_x = 5.698402909980532E-4;
  107. mdelt_y = 5.698402909980532E-4;
  108. }
  109. LatLng kalmanFilter(double oldValue_x, double value_x, double oldValue_y, double value_y) {
  110. lastLocation_x = oldValue_x;
  111. currentLocation_x = value_x;
  112. // print("pdelt_x $pdelt_x mdelt_x $mdelt_x");
  113. gauss_x = sqrt(pdelt_x! * pdelt_x! + mdelt_x * mdelt_x) + m_Q; //计算高斯噪音偏差
  114. kalmanGain_x = sqrt((gauss_x * gauss_x) / (gauss_x * gauss_x + pdelt_x! * pdelt_x!)) + m_R; //计算卡尔曼增益
  115. estimate_x = kalmanGain_x * (currentLocation_x - lastLocation_x) + lastLocation_x; //修正定位点
  116. mdelt_x = sqrt((1 - kalmanGain_x) * gauss_x * gauss_x); //修正模型偏差
  117. lastLocation_y = oldValue_y;
  118. currentLocation_y = value_y;
  119. gauss_y = sqrt(pdelt_y! * pdelt_y! + mdelt_y * mdelt_y) + m_Q; //计算高斯噪音偏差
  120. kalmanGain_y = sqrt((gauss_y * gauss_y) / (gauss_y * gauss_y + pdelt_y! * pdelt_y!)) + m_R; //计算卡尔曼增益
  121. estimate_y = kalmanGain_y * (currentLocation_y - lastLocation_y) + lastLocation_y; //修正定位点
  122. mdelt_y = sqrt((1 - kalmanGain_y) * gauss_y * gauss_y); //修正模型偏差
  123. return LatLng(estimate_y, estimate_x);
  124. }
  125. /***************************卡尔曼滤波结束**********************************/
  126. /***************************抽稀算法*************************************/
  127. List<LatLng>? reducerVerticalThreshold(List<LatLng>? inPoints, double threshHold) {
  128. if (inPoints == null) {
  129. return null;
  130. }
  131. if (inPoints.length <= 2) {
  132. return inPoints;
  133. }
  134. List<LatLng> ret = [];
  135. for (int i = 0; i < inPoints.length; i++) {
  136. LatLng? pre = getLastLocation(ret);
  137. LatLng cur = inPoints[i];
  138. if (pre == null || i == inPoints.length - 1) {
  139. ret.add(cur);
  140. continue;
  141. }
  142. LatLng next = inPoints[i + 1];
  143. double distance = calculateDistanceFromPoint(cur, pre, next);
  144. if (distance > threshHold) {
  145. ret.add(cur);
  146. }
  147. }
  148. return ret;
  149. }
  150. static LatLng? getLastLocation(List<LatLng>? oneGraspList) {
  151. if (oneGraspList == null || oneGraspList.length == 0) {
  152. return null;
  153. }
  154. int locListSize = oneGraspList.length;
  155. LatLng lastLocation = oneGraspList[locListSize - 1];
  156. return lastLocation;
  157. }
  158. /**
  159. * 计算当前点到线的垂线距离
  160. * @param p 当前点
  161. * @param lineBegin 线的起点
  162. * @param lineEnd 线的终点
  163. *
  164. */
  165. /***************************抽稀算法结束*********************************/
  166. List<LatLng>? reduceNoisePoint(List<LatLng>? inPoints, double threshHold) {
  167. if (inPoints == null) {
  168. return null;
  169. }
  170. if (inPoints.length <= 2) {
  171. return inPoints;
  172. }
  173. List<LatLng> ret = [];
  174. for (int i = 0; i < inPoints.length; i++) {
  175. LatLng? pre = getLastLocation(ret);
  176. LatLng cur = inPoints[i];
  177. if (pre == null || i == inPoints.length - 1) {
  178. ret.add(cur);
  179. continue;
  180. }
  181. LatLng next = inPoints[i + 1];
  182. double distance = calculateDistanceFromPoint(cur, pre, next);
  183. if (distance < threshHold) {
  184. ret.add(cur);
  185. }
  186. }
  187. return ret;
  188. }
  189. }
  190. double calculateDistanceFromPoint(LatLng p, LatLng lineBegin, LatLng lineEnd) {
  191. double A = p.longitude - lineBegin.longitude;
  192. double B = p.latitude - lineBegin.latitude;
  193. double C = lineEnd.longitude - lineBegin.longitude;
  194. double D = lineEnd.latitude - lineBegin.latitude;
  195. double dot = A * C + B * D;
  196. double len_sq = C * C + D * D;
  197. double param = dot / len_sq;
  198. double xx, yy;
  199. if (param < 0 || (lineBegin.longitude == lineEnd.longitude && lineBegin.latitude == lineEnd.latitude)) {
  200. xx = lineBegin.longitude;
  201. yy = lineBegin.latitude;
  202. // return -1;
  203. } else if (param > 1) {
  204. xx = lineEnd.longitude;
  205. yy = lineEnd.latitude;
  206. // return -1;
  207. } else {
  208. xx = lineBegin.longitude + param * C;
  209. yy = lineBegin.latitude + param * D;
  210. }
  211. return calculateLineDistance(p.latitude, p.longitude, yy, xx);
  212. }
  213. double calculateDistanceFromPointLatLng(LatLng l1, LatLng l2, LatLng l3) {
  214. return calculateDistanceFromPoint(l1, l2, l3);
  215. }
  216. double calculateLatLngDistance(LatLng var0, LatLng var1) {
  217. if (var0 != null && var1 != null) {
  218. return calculateLineDistance(var0.latitude, var0.longitude, var1.latitude, var1.longitude);
  219. }
  220. return 0.0;
  221. }
  222. double calculateLineDistance(double _lat0, double _lon0, double _lat1, double _lon1) {
  223. try {
  224. double var2 = _lon0;
  225. double var4 = _lat0;
  226. double var6 = _lon1;
  227. double var8 = _lat1;
  228. var2 *= 0.01745329251994329;
  229. var4 *= 0.01745329251994329;
  230. var6 *= 0.01745329251994329;
  231. var8 *= 0.01745329251994329;
  232. double var10 = sin(var2);
  233. double var12 = sin(var4);
  234. double var14 = cos(var2);
  235. double var16 = cos(var4);
  236. double var18 = sin(var6);
  237. double var20 = sin(var8);
  238. double var22 = cos(var6);
  239. double var24 = cos(var8);
  240. List<double> var28 = List.filled(3, 0);
  241. List<double> var29 = List.filled(3, 0);
  242. var28[0] = var16 * var14;
  243. var28[1] = var16 * var10;
  244. var28[2] = var12;
  245. var29[0] = var24 * var22;
  246. var29[1] = var24 * var18;
  247. var29[2] = var20;
  248. return asin(sqrt(
  249. (var28[0] - var29[0]) * (var28[0] - var29[0]) + (var28[1] - var29[1]) * (var28[1] - var29[1]) + (var28[2] - var29[2]) * (var28[2] - var29[2])) /
  250. 2.0) *
  251. 1.27420015798544E7;
  252. } catch (Throwable) {}
  253. return 0.0;
  254. }