Finding a 4th point in 3D space knowing 3 other points and 2 distances to the 4th point from them
Solution 1:
(This is not an answer to the stated question per se, but explains how to efficiently do trilateration.)
In 3D, you need four fixed points (that are not all on the same plane), and their distances to the unknown point, to exactly determine the location of the unknown point.
Three fixed points (that are not all on the same line) and their distances to the unknown point will typically give you two possibilities, symmetrically mirrored by the plane formed by the three fixed points.
Let's say the unknown point is at $\vec{p} = (x, y, z)$, the three fixed points are at $\vec{v}_1 = (x_1 , y_1 , z_1)$, $\vec{v}_2 = (x_2 , y_2 , z_2)$, and $\vec{v}_3 = (x_3 , y_3 , z_3)$, at distances $d_1$, $d_2$, and $d_3$ from the unknown point, respectively. Solving the system of equations $$\left\lbrace\begin{aligned} \left\lVert \vec{p} - \vec{p}_1 \right\rVert &= \lvert d_1 \rvert \\ \left\lVert \vec{p} - \vec{p}_2 \right\rVert &= \lvert d_2 \rvert \\ \left\lVert \vec{p} - \vec{p}_3 \right\rVert &= \lvert d_3 \rvert \\ \end{aligned}\right . \iff \left\lbrace\begin{aligned} (x - x_1)^2 + (y - y_1)^2 + (z - z_1)^2 &= d_1^2 \\ (x - x_2)^2 + (y - y_2)^2 + (z - z_2)^2 &= d_2^2 \\ (x - x_3)^2 + (y - y_3)^2 + (z - z_3)^2 &= d_3^2 \\ \end{aligned}\right.$$ is nontrivial, especially in algebraic form.
Instead, change to a coordinate system where $(x_1 , y_1 , z_1)$ is at origin, $(x_2 , y_2 , z_2)$ is at $(h , 0 , 0)$, and $(x_3 , y_3 , z_3)$ is at $(i, j, 0)$. The unit vectors $\hat{e}_1 = ( X_1 , Y_1 , Z_1 )$, $\hat{e}_2 = ( X_2 , Y_2 , Z_2 )$, and $\hat{e}_3 = (X_3 , Y_3 , Z_3 )$ are $$\left\lbrace\begin{aligned} \vec{e}_1 &= \vec{v}_2 - \vec{v}_1 \\ \hat{e}_1 &= \frac{\vec{e}_1}{\left\lVert\vec{e}_1\right\rVert} \\ \vec{e}_2 &= \vec{v}_3 - \vec{v}_1 - \hat{e}_1 \left ( \hat{e}_1 \cdot \left ( \vec{v}_3 - \vec{v}_1 \right ) \right ) \\ \hat{e}_2 &= \frac{\vec{e}_2}{\left\lVert\vec{e}_2\right\rVert} \\ \hat{e}_3 &= \hat{e}_1 \times \hat{e}_2 \\ \end{aligned}\right.$$ and the fixed point coordinates are $$\left\lbrace\begin{aligned} h &= \left\lVert \vec{v}_2 - \vec{v}_1 \right\rVert = \sqrt{ (x_2 - x_1)^2 + (y_2 - y_1)^2 + (z_2 - z_1)^2 } \\ i &= \hat{e}_1 \cdot \left(\vec{v}_3 - \vec{v}_1\right) = X_1 ( x_3 - x_1 ) + Y_1 ( y_3 - y_1 ) + Z_1 ( Z_3 - Z_1 ) \\ j &= \hat{e}_2 \cdot \left(\vec{v}_3 - \vec{v}_1\right) = X_2 ( x_3 - x_1 ) + Y_2 ( y_2 - y_1 ) + Z_2 ( Z_3 - Z_2 ) \\ \end{aligned}\right.$$ The distances stay the same, but the system of equations is much simpler. For clarity, I'll use $(u, v, w)$ in these new coordinates instead of $(x, y, z)$: $$\left\lbrace\begin{aligned} u^2 + v^2 + w^2 &= d_1^2 \\ (u - h)^2 + v^2 + w^2 &= d_2^2 \\ (u - i)^2 + (v - j)^2 + w^2 &= d_3^2 \end{aligned}\right.$$ which is easily solved: $$\left\lbrace\begin{aligned} u &= \frac{d_1^2 - d_2^2 + h^2}{2 h} \\ v &= \frac{d_1^2 - d_3^2 + i^2 + j^2 - 2 i u}{2 j} \\ w &= \pm \sqrt{d_1^2 - u^2 - v^2} \\ \end{aligned}\right.$$ In the original coordinate system, $$\vec{p} = \vec{v}_1 + u \hat{e}_1 + v \hat{e}_2 + w \hat{e}_3 \quad \iff \quad \left\lbrace\begin{aligned} x &= x_1 + u X_1 + v X_2 + w X_3 \\ y &= y_1 + u Y_1 + v Y_2 + w Y_3 \\ z &= z_1 + u Z_1 + v Z_2 + w Z_3 \\ \end{aligned}\right.$$ noting that if $w$ is not a real, then there is no solution; if $w \approx 0$, there is one solution; and otherwise there are two solutions, one with positive $w$, and the other with negative $w$.
If you know the distances to four fixed points, you only really need the fourth point (not coplanar with the three other fixed points) to distinguish which case it is. If the distances contain noise, it might make sense to calculate the result using each unique triplet ($123$, $124$, $134$, and $234$), and return their mean.
In pseudocode, for trilateration, you should precalculate the values that only depend on the fixed points:
Let ex1 = x2 - x1
Let ey2 = y2 - y1
Let ez2 = z2 - z1
Let h = sqrt( ex1*ex1 + ey1*ey1 + ez1*ez1 )
If h <= epsilon:
Error: First and second point are too close.
End If
Let ex1 = ex1 / h
Let ey1 = ey1 / h
Let ez1 = ez1 / h
Let i = ex1*(x2 - x1) + ey1*(y2 - y1) + ez1*(z2 - z1)
Let ex2 = x3 - x1 - i*ex1
Let ey2 = y3 - y1 - i*ey1
Let ez2 = z3 - z1 - i*ez1
Let t = sqrt(ex2*ex2 + ey2*ey2 + ez2*ez2)
If t <= epsilon:
Error: the three fixed points are too close to being on the same line.
End If
Let ex2 = ex2 / t
Let ey2 = ey2 / t
Let ez2 = ez2 / t
Let j = ex2*(x3 - x1) + ey2*(y3 - y1) + ez2*(z3 - z1)
If j <= epsilon and j >= -epsilon:
Error: the three fixed points are too close to being on the same line.
End If
Let ex3 = ey1*ez2 - ez1*ey2
Let ey3 = ez1*ex2 - ex1*ez2
Let ez3 = ex1*ey2 - ey2*ex1
where epsilon
is the largest positive number that should be treated as zero, and represents the expected precision in coordinates and distances, for example 0.001
.
The function that finds the coordinates for the unknown point is then
# Fixed points are at (x1,y1,z1), (x2,y2,z2), (x3,y3,z3)
# Function takes the distances to fixed points d1, d2, d3
# Function expects unit vectors (ex1,ey1,ez1), (ex2,ey2,ez2), (ex3,ey3,ez3)
# to be precalculated, with fixed points at (0,0,0), (h,0,0), (i,j,0)
# in that coordinate system, without changing the distances
Function Trilaterate(d1, d2, d3):
Let u = (d1*d1 - d2*d2 + h*h) / (2*h)
Let v = (d1*d1 - d3*d3 + i*(i - 2*u) + j*j) / (2*j)
Let ww = d1*d1 - u*u - v*v
If ww < -epsilon:
Return no solutions
Else
If ww < epsilon:
Return a single solution:
x = x1 + u*ex1 + v*ex2
y = y1 + u*ey1 + v*ey2
z = z1 + u*ez1 + v*ez2
Else:
w = sqrt(ww)
Return two solutions:
x = x1 + u*ex1 + v*ex2 + w*ex3
y = y1 + u*ey1 + v*ey2 + w*ey3
z = z1 + u*ez1 + v*ez2 + w*ez3
And
x = x1 + u*ex1 + v*ex2 - w*ex3
y = y1 + u*ey1 + v*ey2 - w*ey3
z = z1 + u*ez1 + v*ez2 - w*ez3
End If
End Function
This is simple enough to be done on 8-bit microcontrollers, if necessary.