Трилатерация и определение точки (x, y, z)

Я хочу найти координату неизвестного узла, который находится где-то в пространстве, которое имеет опорное расстояние от 3 или более узлов, все из которых имеют известную координату.

Эта проблема точно такая же, как Трилатерация, описанная здесь Трилатерация.

Однако я не понимаю часть о «Предварительных и окончательных вычислениях» (см. сайт википедии). Я не понимаю, где я могу найти P1, P2 и P3, чтобы я мог составить это уравнение?

Спасибо


person CB4    schedule 23.04.2013    source источник


Ответы (3)


Трилатерация — это процесс нахождения центра области пересечения трех сфер. Центр и радиус каждой из трех сфер должны быть известны.

Давайте рассмотрим ваши три примера центральных точек 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 = (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

Если P2' не лежит на оси x после перевода P1 в начало координат, мы должны выполнить поворот вида.

Во-первых, давайте создадим несколько новых векторов для примера: 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).

Мы можем использовать равенство множественного произведения:

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

Когда B равно [1,0], это можно упростить: точка B всегда является просто компонентом X точки A, а ||B|| (величина B) всегда является умножением на 1 и поэтому может быть проигнорирована.

Теперь у нас есть Ах = ||А|| cos(theta), которое мы можем преобразовать в наше окончательное уравнение:

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

или в нашем случае:

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

Мы вычисляем величину P2', используя ||A|| = sqrt(Ax + Ay + Az)

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

Подключив это, мы можем решить для тета

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

Теперь воспользуемся матрицей вращения, чтобы повернуть сцену на -45 градусов. Поскольку P2'y положителен, а матрица вращения вращается против часовой стрелки, мы будем использовать отрицательное вращение, чтобы выровнять P2 по оси x (если P2'y отрицательно, не отрицайте тета).

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(-тета), в данном случае R(45). Чтобы отменить перевод, вычтите вектор смещения V, что аналогично добавлению P1 (при условии, что вы изначально использовали -P1 в качестве V).

person Dan Bechard    schedule 23.04.2013
comment
Я не знаю, как я получаю эти точки P1, P2 и P3. Я имею в виду, что для каждого эталонного известного узла у меня есть координата x, y, z. - person CB4; 23.04.2013
comment
P1 — это точка (которая состоит из пары координат X, Y) в центре первого опорного узла. Аналогично для P2 и P3. Если у вас есть опорные координаты, у вас есть P1, P2 и P3. Это одно и то же. - person Dan Bechard; 24.04.2013
comment
Я установил тестовые координаты только для проверки математики, и это не дало мне правильного результата, поэтому я запутался. Это моя установка: p1 = (-1,1) p2 = (1,1) p3 = (-1,-1) Из уравнения, которое я нашел: ex = (1,0) i = 0 ey = (0 ,-1) d = 2, поэтому, чтобы найти x и y, используйте другие уравнения, и я получаю x = 1 y = 1, что неверно. Я ожидаю увидеть x = 0 и y = 0. Примечание. В этом случае я использую r1 = sqrt(2) = r2 = r3. Можете ли вы найти проблему в расчете? - person CB4; 24.04.2013
comment
Я переписал свой ответ, надеюсь, он будет намного полезнее. Дайте мне знать, если это все еще не имеет смысла. - person Dan Bechard; 27.04.2013
comment
@Dan: Я изучал ту же страницу в Википедии и наткнулся на ваш ответ, он очень помог мне понять эту концепцию. Я внедрил первую часть статьи в алгоритм, однако у меня возникли проблемы со второй частью (т.е. переводами). Не могли бы вы привести пример сценария с координатами, где также необходимо второе требование (т.е. перемещение P2' по оси X)? - person Yazid; 23.12.2013
comment
@Yazid: я отредактировал свой ответ, включив в него шаг для поворота сцены, чтобы выровнять P2 'с осью x. Пожалуйста, не стесняйтесь обращаться за разъяснениями или предлагать исправления любых ошибок, которые вы можете найти. Надеюсь, поможет. - person Dan Bechard; 24.12.2013
comment
@Dan: Попробовал, не уверен на 100% в своем переводе математики в мой алгоритм, но я получил P4 = [4.5,5.5]. Это правильно? - person Yazid; 24.12.2013
comment
@Yazid: Это зависит от того, что вы приняли за радиус трех кругов. Я предоставил только центральные точки для примера перевода/поворота. Чтобы триангулировать P4, центральную точку пересечения окружностей, вам нужно использовать P1'', P2'' и P3'', чтобы найти P4'', что означает включение скорректированных центральных точек и их соответствующих радиусов в уравнения в первой половине (где я принял радиус = 2 для всех трех кругов). - person Dan Bechard; 24.12.2013
comment
@Dan: Да, я проверил ваши последние координаты P1 P2 P3 выше и принял радиус 2 для всех трех. Просто хотел проверить мой алгоритм, чтобы увидеть, работает ли математика с вашим. Если вы также получили [4.5, 5.5], я, вероятно, сочту это правильным. - person Yazid; 24.12.2013
comment
@Yazid: Если вы нарисуете круги, вы должны увидеть, что центр их пересечения примерно [3.5, 2.5]. Вы забыли применить перевод в конце, чтобы вернуться к исходной системе координат? - person Dan Bechard; 30.12.2013
comment
@Dan: Извините, в моей формуле P4''x были ошибки в скобках, из-за которых расчеты были неверными. Теперь он возвращает [3.5, 2.5], поэтому, похоже, он работает для вышеуказанного набора координат. Однако, когда я немного меняю сценарий, то есть P3 = [5,1], я получаю P4 = [4,5, 3,5]. Когда круги нарисованы, визуально я бы предположил, что результат будет примерно [3.6, 2.3]. Я не думаю, что это мои оригинальные переводы, так как я получаю [0,0], [0, 1,414] и [2,828, 0,1414] для P1 '' P2 '' и P3 '' соответственно, как и у вас. Возможно, это мои формулы P4''. Мои конечные переводы уже применены и работают корректно. - person Yazid; 02.01.2014
comment
@Yazid: Это может быть ошибка в ротации. Поскольку он вращается против часовой стрелки, вам может понадобиться использовать -45 вместо 45 (при условии, что угол равен 45, как в приведенном выше примере). Это зависит от того, в какую сторону нужно повернуть вектор, чтобы выровнять его по оси x. Цель состоит в том, чтобы получить P1 в начале координат и P2 на оси X. Как именно вы туда доберетесь, не важно, если вы не забудете отменить шаги, которые вы использовали после триангуляции в новой системе координат, чтобы вернуться к исходной системе координат. - person Dan Bechard; 02.01.2014
comment
@Yazid: я исправил ошибку знака в сообщении относительно R (-45). Возможно, это поможет вам. - person Dan Bechard; 02.01.2014
comment
@Dan: Это помогло! Большое спасибо, вы очень помогли. Математика теперь довольно здравая. К вашему сведению, мне удалось добиться того же результата в определении угла поворота, выполнив ATAN2(P2'x-P1'x, P2'y-P1'y). Кроме того, я обнаружил, что формула, которую я имею, ломается (с ошибкой деления на ноль), если все круги имеют одинаковое значение Y. Это формула P4''y, которая производит его, особенно часть (i/j) (когда все Y равны, j = 0). В моем приложении это будет редкий сценарий, поэтому лично я готов принять его, но, тем не менее, интересно выделить его для обсуждения. - person Yazid; 03.01.2014
comment
@Dan: Просто добавлю, что по сути ошибка возникает всякий раз, когда все повернутые координаты лежат на одной оси x. Например. P1 = [0, 0], P2 = [1, 1] и P3 [2, 2] также сделают это. - person Yazid; 03.01.2014
comment
@Yazid: Ах да, ATAN2, по сути, является версией ATAN с исправлением знаков, которая учитывает, в каком квадранте находятся точки. Довольно изящная функция, но ее доступность зависит от вашего набора инструментов. Правильно, j = 0 происходит, когда центральные точки расположены вдоль одной оси, что делает невозможным их соединение в треугольник. Без треугольника не может быть триангуляции. - person Dan Bechard; 04.01.2014
comment
@Yazid: В этом случае лучше всего отбросить среднюю точку и найти две точки пересечения двух оставшихся кругов, а затем усреднить их, чтобы получить центр пересечения. См.: math.stackexchange.com/questions/256100/ Если есть только одна точка пересечения, нет необходимости усреднять, просто используйте эту точку. Если нет точек пересечения, ваши данные не являются данными триангуляции (что предполагает, что все три круга/сферы имеют по крайней мере одну общую точку), и это совершенно другая проблема. - person Dan Bechard; 04.01.2014
comment
@merveotesi Надеюсь, это поможет, не стесняйтесь оставлять комментарии или начинать обсуждение, если у вас есть какие-либо вопросы. - person Dan Bechard; 14.08.2014
comment
@ Дэн, мне нужно указать область. Не точка, а интервал. Но функции вроде бы дают баллы. Считаете ли вы, что это правильный способ сделать цикл for и рассмотреть все полученные значения для 0‹r‹r1 и для других переменных. - person merveotesi; 19.08.2014
comment
Что такое площадь, интервал в контексте вашей задачи? Возможно, вам стоит задать свой вопрос и оставить ссылку здесь. - person Dan Bechard; 19.08.2014
comment
@ Дэн, я снова прочитал пост и обнаружил, что точка x, y является центральной точкой. Я не знал, что мы получаем центр. это нормально на данный момент. Спасибо - person merveotesi; 19.08.2014
comment
вау... я не знал, что у этой ветки столько просмотров с тех пор, как я в последний раз просматривал ее пару лет назад. @ Дэн. Спасибо за помощь. Мне удалось успешно локализовать в помещении несколько узлов. Тем не менее, я использовал точки доступа Wi-Fi в качестве узлов, и, поскольку диапазон 2,4/5 ГГц не слишком хорош для проникновения через стены, я остановился на этом. Программа работает хорошо, Wi-Fi практически не блокируется. - person CB4; 26.05.2016
comment
@ user1801381 Рад, что помог. :) - person Dan Bechard; 26.05.2016

Это алгоритм, который я использую в прошивке для 3D-принтера. Он позволяет избежать поворота системы координат, но, возможно, он не самый лучший.

Есть 2 решения проблемы трилатерации. Чтобы получить второе, замените «- sqrtf» на «+ sqrtf» в решении квадратного уравнения.

Очевидно, вы можете использовать двойные числа вместо поплавков, если у вас достаточно мощности процессора и памяти.

// Primary parameters
float anchorA[3], anchorB[3], anchorC[3];               // XYZ coordinates of the anchors

// Derived parameters
float Da2, Db2, Dc2;
float Xab, Xbc, Xca;
float Yab, Ybc, Yca;
float Zab, Zbc, Zca;
float P, Q, R, P2, U, A;

...

inline float fsquare(float f) { return f * f; }

...

// Precompute the derived parameters - they don't change unless the anchor positions change.
Da2 = fsquare(anchorA[0]) + fsquare(anchorA[1]) + fsquare(anchorA[2]);
Db2 = fsquare(anchorB[0]) + fsquare(anchorB[1]) + fsquare(anchorB[2]);
Dc2 = fsquare(anchorC[0]) + fsquare(anchorC[1]) + fsquare(anchorC[2]);
Xab = anchorA[0] - anchorB[0];
Xbc = anchorB[0] - anchorC[0];
Xca = anchorC[0] - anchorA[0];
Yab = anchorA[1] - anchorB[1];
Ybc = anchorB[1] - anchorC[1];
Yca = anchorC[1] - anchorA[1];
Zab = anchorB[2] - anchorC[2];
Zbc = anchorB[2] - anchorC[2];
Zca = anchorC[2] - anchorA[2];
P = (  anchorB[0] * Yca
     - anchorA[0] * anchorC[1]
     + anchorA[1] * anchorC[0]
     - anchorB[1] * Xca
    ) * 2;
P2 = fsquare(P);
Q = (  anchorB[1] * Zca
     - anchorA[1] * anchorC[2]
     + anchorA[2] * anchorC[1]
     - anchorB[2] * Yca
    ) * 2;  

R = - (  anchorB[0] * Zca
       + anchorA[0] * anchorC[2]
       + anchorA[2] * anchorC[0]
       - anchorB[2] * Xca
      ) * 2;
U = (anchorA[2] * P2) + (anchorA[0] * Q * P) + (anchorA[1] * R * P);
A = (P2 + fsquare(Q) + fsquare(R)) * 2;

...

// Calculate Cartesian coordinates given the distances to the anchors (La, Lb and Lc)
// First calculate PQRST such that x = (Qz + S)/P, y = (Rz + T)/P.
// P, Q and R depend only on the anchor positions, so they are pre-computed
const float S = - Yab * (fsquare(Lc) - Dc2)
                - Yca * (fsquare(Lb) - Db2)
                - Ybc * (fsquare(La) - Da2);
const float T = - Xab * (fsquare(Lc) - Dc2)
                + Xca * (fsquare(Lb) - Db2)
                + Xbc * (fsquare(La) - Da2);

// Calculate quadratic equation coefficients
const float halfB = (S * Q) - (R * T) - U;
const float C = fsquare(S) + fsquare(T) + (anchorA[1] * T - anchorA[0] * S) * P * 2 + (Da2 - fsquare(La)) * P2;

// Solve the quadratic equation for z
float z = (- halfB - sqrtf(fsquare(halfB) - A * C))/A;

// Substitute back for X and Y
float x = (Q * z + S)/P;
float y = (R * z + T)/P;
person dc42    schedule 27.11.2017

Вот расчеты из Википедии, представленные в скрипте OpenSCAD, которые, как мне кажется, помогают визуально понять проблему и дают простой способ проверить правильность результатов. Пример вывода скрипта

// 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);
      }
  }
}
person QuatCoder    schedule 26.09.2018