【原創】大叔案例分享(4)定位分析--見證scala的強大

一 場景分析

定位分析普遍應用,好比室外基站定位,室內藍牙beacon定位,室內wifi探針定位等,實現方式是三點定位 Trilaterationhtml

理想狀況

 

這種理想狀況要求3個基站‘同時’採集‘準確’的距離信息,算法

實際狀況

  • 3個基站採集數據的時間是分開的;
  • 採集數據的距離不許確;

解決方法是:app

  • 增長基站數量,即增長採集數據的密度和數量;
  • 不採用一個時間點的數據,而採用一個時間段的數據計算,好比5s內可能只有1個基站的數據,可是30s內可能會有超過3個基站的數據;
  • 在偏差範圍內,採用數學方法迭代收斂,找出機率上最有可能的未知點的座標;

獲得未知點座標以後再結合時間能夠作更多應用:軌跡圖,熱力圖等,好比測試

二 問題抽象

已知條件

  • n個點位置座標:(x1, y1), (x2, y2), (x3, y3), ..., (xn, yn)
  • 未知點到n個點距離:d1, d2, d3, ..., dn

求解

  • 未知點位置座標(x, y)

方程

 

解法

上面的方程是n個2次方程,spa

1)首先嚐試將次數下降,逐個用方程組中第i-1個方程減去第i個方程獲得新方程,這樣n個2次方程轉換爲n-1個1次方程,scala

2)獲得n-1個1次方程(線性方程)以後,問題轉換爲一元線性迴歸問題:3d

即平面中有n個觀察點(x1, y1), (x2, y2), ..., (xn, yn),須要找到一條直線Y=aX+b,計算常數a和常數b使得n個觀察點到直線的距離(偏差)平方和最小(注意原始問題中的未知點座標就是這裏的常數a和常數b);code

 

一元線性迴歸模型能夠利用最小二乘法(最小平方法)求得最優解,即最小二乘解;最小二乘法詳見:http://www.javashuo.com/article/p-wezqqmww-ha.htmlhtm

 

問題模型簡化

(x1, y1, d1)
(x2, y2, d2)
...
(xn, yn, dn)
->
(x, y)blog

三 統計示例

輸入
(1.0, 1.0, 1.0)
(2.0, 0.0, 1.0)
(2.0, 2.0, 1.0)

輸出
(2.0,1.0)

四 代碼實現

scala核心代碼

scala

 

  /**
    * @param datas Array(x_coordinates, y_coordinates, distance)
    * @return (x_coordinates, y_coordinates)
    */
  def detect(datas : Array[(Double, Double, Double)]) : (Double, Double) = {
    if (datas == null || datas.isEmpty) (0, 0)
    else if (datas.length == 1) return (datas.head._1, datas.head._2)
    else if (datas.length == 2) return ((datas.head._1 + datas.last._1) / 2, (datas.head._2 + datas.last._2) / 2)
    else {
      var data = Array[Array[Double]]()
      //X + (y_1 - y_i)/(x_1 - x_i)Y = (sq(d_i) - sq(d_1) + sq(x_1) + sq(y_1) - sq(x_i) - sq(y_i))/2(x_1 - x_i)
      for (i <- 1 to (datas.length - 1)) data = data :+ Array((datas.head._2 - datas.apply(i)._2) / (datas.head._1 - datas.apply(i)._1), (Math.pow(datas.apply(i)._3, 2) - Math.pow(datas.head._3, 2) + Math.pow(datas.head._1, 2) + Math.pow(datas.head._2, 2) - Math.pow(datas.apply(i)._1, 2) - Math.pow(datas.apply(i)._2, 2))  / 2 / (datas.head._1 - datas.apply(i)._1))
      val regression = new SimpleRegression
      regression.addData(data)
      (regression.getIntercept, regression.getSlope)
    }
  }

測試運行

      println(detect(Array((1.0, 1.0, 1.0))))
      println(detect(Array((1.0, 1.0, 1.0), (2.0, 2.0, 1.0))))
      println(detect(Array((1.0, 1.0, 1.0), (2.0, 0.0, 1.0), (2.0, 2.0, 1.0))))
      println(detect(Array((1.0, 1.0, 1.0), (2.0, 0.0, 1.0), (2.0, 3.0, 1.0))))
      println(detect(Array((1.0, 1.0, 1.0), (2.0, 0.0, 1.0), (2.0, 3.0, 1.0), (2.0, 3.0, 1.0), (20.0, 30.0, 1.0))))

輸出

(1.0,1.0)
(1.5,1.5)
(2.0,1.0)
(2.5,1.5)
(7.728915662650602,3.3674698795180724)

五 半徑圖效果

實際數據的半徑圖示例:

半徑圖中黑色點表示基站位置,每一個基站都有一個或兩個圓圈,其中兩個圓圈使用數據裏的最大距離和最小距離繪製的;紅色點表示根據算法定位出來的設備位置;

相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息