给定三个接收器的位置和它们接收信号的时间(到达时间延迟),如何定位信号?

Kei*_*son 6 algorithm math mathematical-optimization

我有 3 个接收器(A、B 和 C),以及一些位置未知的信号产生源(比如说声音或光)。给定 A、B 和 C 的位置,以及每个接收器“听到”信号的时间,我想确定源的方向。

我知道有一些方法可以通过 TDoA 多边/三边测量来实现,但是我在实现计算时遇到了麻烦。对于那些完全不熟悉该主题的人,没有很多关于此的清晰、详细的信息。外面的东西是模糊的,更理论化的,或者对我来说有点太深奥了。

SO 上的一些类似帖子(但不完全是我所追求的): TDOA 多点定位以定位声源 使用时差(TDOA)对信号进行三边测量

这也很有趣,但假设我们有一些界限: 距离数据不准确的多文字实现

@Dave 还评论了一个优秀且相当易于访问的资源https://sites.tufts.edu/eeseniordesignhandbook/files/2017/05/FireBrick_OKeefe_F1.pdf,但它没有达到足够的深度,以至于人们可能能够实际实现这一点在代码中(至少,对于没有深入了解回归知识的人,找到结果双曲线的交集等)。

[编辑]:我应该补充一点,我可以假设 3 个传感器源位于地球表面,并且地球曲率的影响可以忽略不计(即我们可以在二维中工作)。

Spe*_*tre 2

有趣的问题。我懒得推导代数解方程。相反,为什么不适合结果呢?

因此,只需使用能够找到局部解决方案的任何拟合方法(使用某些误差值的优化/最小化)来拟合 2D(或更高)位置即可。当我使用我的简单近似搜索来拟合位置时,结果看起来相当不错。

算法是:

  1. 迭代范围内的“所有”位置

    粗略的拟合并不是所有的启发式方法都会大大减少问题。

  2. 在每个测试位置计算将测量的增量时间

    从测试位置到接收站的简单行进时间。

  3. 标准化所有增量时间,以便从零开始

    因此,从所有接收者时间中减去最小到达时间。对于实际测量的时间也是如此。这确保了时间不涉及相对偏移。

  4. 计算实际测量时间和计算时间之间的差异

    简单的腹肌差异就足够了。使用该值作为拟合参数(优化)。

这里是一个小的 C++ 示例,使用上面链接中的我的 approx 类来执行此操作:

//---------------------------------------------------------------------------
// TDoA Time Difference of Arrival
//---------------------------------------------------------------------------
const int n=3;
double recv[n][3];  // (x,y) [m] receiver position,[s] time of arrival of signal
double pos0[2];     // (x,y) [m] object's real position
double pos [2];     // (x,y) [m] object's estimated position
double v=340.0;     // [m/s] speed of signal
double err=0.0;     // [m] error between real and estimated position
//---------------------------------------------------------------------------
void compute()
    {
    int i;
    double x,y,a,da,t0;
    //---------------------------------------------------------
    // init positions
    da=2.0*M_PI/(n);
    for (a=0.0,i=0;i<n;i++,a+=da)
        {
        recv[i][0]=256.0+(220.0*cos(a));
        recv[i][1]=256.0+(220.0*sin(a));
        }
    pos0[0]=300.0;
    pos0[1]=220.0;
    // simulate measurement
    t0=123.5;                   // some start time
    for (i=0;i<n;i++)
        {
        x=recv[i][0]-pos0[0];
        y=recv[i][1]-pos0[1];
        a=sqrt((x*x)+(y*y));    // distance to receiver
        recv[i][2]=t0+(a/v);    // start time + time of travel
        }
    //---------------------------------------------------------
    // normalize times into deltas from zero
    a=recv[0][2]; for (i=1;i<n;i++) if (a>recv[i][2]) a=recv[i][2];
    for (i=0;i<n;i++) recv[i][2]-=a;
    // fit position
    int N=6;
    approx ax,ay;
    double e,dt[n];
              // min,  max,step,recursions,&error
    for (ax.init( 0.0,512.0, 32.0        ,N,   &e);!ax.done;ax.step())
     for (ay.init(  0.0,512.0, 32.0       ,N,   &e);!ay.done;ay.step())
        {
        // simulate measurement -> dt[]
        for (i=0;i<n;i++)
            {
            x=recv[i][0]-ax.a;
            y=recv[i][1]-ay.a;
            a=sqrt((x*x)+(y*y));    // distance to receiver
            dt[i]=a/v;              // time of travel
            }
        // normalize times dt[] into deltas from zero
        a=dt[0]; for (i=1;i<n;i++) if (a>dt[i]) a=dt[i];
        for (i=0;i<n;i++) dt[i]-=a;
        // error
        e=0.0; for (i=0;i<n;i++) e+=fabs(recv[i][2]-dt[i]);
        }
    pos[0]=ax.aa;
    pos[1]=ay.aa;
    //---------------------------------------------------------
    // compute error
    x=pos[0]-pos0[0];
    y=pos[1]-pos0[1];
    err=sqrt((x*x)+(y*y));  // [m]
    }
//---------------------------------------------------------------------------
Run Code Online (Sandbox Code Playgroud)

这里预览:

预览

蓝点是接收器,红点是物体的真实位置,黄十字是其估计位置。该区域是,我用初始步骤和递归512x512 m来拟合它,导致错误32 m6~0.005 m

我对结果非常满意...您可以更改接收器的数量,n而无需对源或算法进行任何真正的更改。我将接收器位置初始化为均匀分布在圆上,但位置可能是任何其他位置(并非全部在单条粗线上)