三角测量和定位点(x,y,z)

时间:2013-04-23 18:32:58

标签: algorithm localization geometry triangulation trilateration

我想找到一个位于空间某处的未知节点的坐标,该节点的参考距离远离3个或更多节点,所有这些节点都已知有坐标。

此问题与此处描述的Trilateration Trilateration完全相同。

但是,我不理解关于“初步和最终计算”的部分(参考维基百科网站)。我找不到P1,P2和P3的地方,所以我可以把它们放到那些方程式上?

由于

2 个答案:

答案 0 :(得分:28)

三边测量是找到三个球体交叉区域中心的过程。必须知道三个球体的中心点和半径。

让我们考虑你的三个例子中心点P1 [-1,1],P2 [1,1]和P3 [-1,-1]。第一个要求是P1'在原点,所以让我们通过在所有三个上加一个偏移矢量V [1,-1]来相应地调整点:

P1' = P1 + V = [0, 0]
P2' = P2 + V = [2, 0]
P3' = P3 + V = [0,-2]

注意:调整后的点由'(素数)注释表示。

P2'也必须位于x轴上。在这种情况下它已经存在,因此无需进行任何调整。

我们假设每个球体的半径为2。

现在我们有3个方程(给定)和3个未知数(交点中心点的X,Y,Z)。

解决P4'x:

x = (r1^2 - r2^2 + d^2) / 2d  //(d,0) are coords of P2'
x = (2^2 - 2^2 + 2^2) / 2*2
x = 1

解决P4'y:

y = (r1^2 - r3^2 + i^2 + j^2) / 2j - (i/j)x //(i,j) are coords of P3'
y = (2^2 - 2^2 + 0 + -2^2) / 2*-2 - 0
y = -1

忽略z以解决2D问题。

P4'= [1,-1]

现在我们通过减去偏移矢量V:

来转换回原始坐标空间

P4 = P4' - V = [0,0]

解决方案点P4正如预期的那样位于原点。

本文的后半部分描述了一种表示一组点的方法,其中P1不在原点,或者P2不在x轴上,使得它们符合这些约束。我更愿意将其视为翻译,但两种方法都会产生相同的解决方案。

编辑:将P2'旋转到x轴

如果在将P1转换为原点后P2'不位于x轴上,我们必须对视图执行旋转。

首先,让我们创建一些新的矢量作为例子: P1 = [2,3] P2 = [3,4] P3 = [5,2]

请记住,我们必须首先将P1翻译为原点。与往常一样,偏移矢量V是-P1。在这种情况下,V = [ - 2,-3]

P1' = P1 + V = [2,3] + [-2,-3] = [0, 0]
P2' = P2 + V = [3,4] + [-2,-3] = [1, 1]
P3' = P3 + V = [5,2] + [-2,-3] = [3,-1]

要确定旋转角度,我们必须找到P2'和[1,0](x轴)之间的角度。

我们可以使用dot product相等:

A dot B = ||A|| ||B|| cos(theta)

当B为[1,0]时,可以简化:点B始终只是A的X分量,|| B || (B的大小)总是乘以1,因此可以忽略。

我们现在有Ax = || A || cos(theta),我们可以重新排列到最终的等式:

theta = acos(Ax / ||A||)

或在我们的案例中:

theta = acos(P2'x / ||P2'||)

我们使用|| A ||计算P2'的大小= sqrt(Ax + Ay + Az)

||P2'|| = sqrt(1 + 1 + 0) = sqrt(2)

插入我们可以解决的问题

theta = acos(1 / sqrt(2)) = 45 degrees

现在让我们使用rotation matrix将场景旋转-45度。 由于P2'y为正,旋转矩阵逆时针旋转,我们将使用负旋转将P2与x轴对齐(如果P2'为负,则不要否定θ)。

R(theta) = [cos(theta) -sin(theta)]
           [sin(theta)  cos(theta)]

  R(-45) = [cos(-45) -sin(-45)]
           [sin(-45)  cos(-45)]

我们将使用双素数符号''来表示已翻译和旋转的矢量。

P1'' = [0,0] (no need to calculate this one)

P2'' = [1 cos(-45) - 1 sin(-45)] = [sqrt(2)] = [1.414]
       [1 sin(-45) + 1 cos(-45)] = [0]       = [0]

P3'' = [3 cos(-45) - (-1) sin(-45)] = [sqrt(2)]    = [ 1.414]
       [3 sin(-45) + (-1) cos(-45)] = [-2*sqrt(2)] = [-2.828]

现在你可以使用P1'',P2''和P3''来解决P4''。将反向旋转应用于P4''以获得P4',然后反向旋转以获得P4,即您的中心点。

要撤消旋转,请将P4''乘以R(-theta),在本例中为R(45)。要撤消平移,请减去偏移矢量V,这与添加P1相同(假设您最初使用-P1作为V)。

答案 1 :(得分:0)

以下是OpenSCAD脚本中提供的Wikipedia计算,我认为这有助于以视觉方式理解问题,并提供一种简便的方法来检查结果是否正确。 Example output from the script

// Trilateration example
// from Wikipedia
// 
// pA, pB and pC are the centres of the spheres
// If necessary the spheres must be translated
// and rotated so that:
// -- all z values are 0
// -- pA is at the origin
pA = [0,0,0];
// -- pB is on the x axis
pB = [10,0,0];
pC = [9,7,0];

// rA , rB and rC are the radii of the spheres
rA = 9;
rB = 5;
rC = 7;


if ( pA != [0,0,0]){
   echo ("ERROR: pA must be at the origin");
   assert(false);
}

if ( (pB[2] !=0 ) || pC[2] !=0){
   echo("ERROR: all sphere centers must be in z = 0 plane");
   assert(false);
}

if (pB[1] != 0){
   echo("pB centre must be on the x axis");
   assert(false);
}

// show the spheres
module spheres(){
   translate (pA){
      sphere(r= rA, $fn = rA * 10);
   }

   translate(pB){
      sphere(r = rB, $fn = rB * 10);
   }

   translate(pC){
      sphere (r = rC, $fn = rC * 10);
   }
}

function unit_vector( v) = v / norm(v);

ex = unit_vector(pB - pA) ;
echo(ex = ex);

i = ex * ( pC - pA);
echo (i = i);

ey = unit_vector(pC - pA - i * ex);
echo (ey = ey);

d = norm(pB - pA);
echo (d = d);

j =  ey * ( pC - pA);
echo (j = j);

x = (pow(rA,2) - pow(rB,2) + pow(d,2)) / (2 * d);
echo( x = x);

// size of the cube to subtract to show 
// the intersection of the spheres
cube_size = [10,10,10];

if ( ((d - rA) >= rB) || ( rB >= ( d + rA)) ){
   echo ("Error Y not solvable");
}else{
   y = (( pow(rA,2) - pow(rC,2) + pow(i,2) + pow(j,2)) / (2 * j))
      - ( i / j) * x;
   echo(y = y);
   zpow2 = pow(rA,2) - pow(x,2) - pow(y,2);
   if ( zpow2 < 0){
      echo ("z not solvable");
   }else{
      z = sqrt(zpow2);
      echo (z = z);
      // subtract a cube with one of its corners 
      // at the point where the sphers intersect
      difference(){
         spheres();
         translate ([x,y - cube_size[1],z]){
           cube(cube_size);
         }
      }
      translate ([x,y - cube_size[1],z]){
           %cube(cube_size);
      }
  }
}