Register or Login to browse without ads

Fri 10 Sep 2010 - 8:31 pm UTC

Home | Ask a Question | Browse Questions

4 stars ANSWERED on Sun 17 Jan 2010 - 7:50 pm UTC by mathtalk

Question: Geometry: Find a 3d location based on 6 angles and 1 length (4PointsAndACamera)

Home » Science and Mathematics » #3601

Please carefully read the Disclaimer and Terms & conditions.
Priced at $50.00
The customer tipped the researcher $70.00

Actions: Add Comment

Asked by eldenc on Fri 8 Jan 2010 - 12:23 am UTC:

Geometry: Find a 3d location based on 6 angles and 1 length
(4PointsAndACamera)

Let A, B, C, and D be four points on the xy plane in a 3 Dimensional
Cartesian space.
Let M represent a point of unknown position in the positive xyz quadrant.

Given that:

   A is as the origin   (0,0,0)
   B is on the x axis   (r,0,0)
   C is on the y axis   (0,r,0)
   D is on the xy plane (r,r,0)
   where r > 0

   The angles AMB, AMC, AMD, BMC, BMD, and CMD are known.

   Optionally, if necessary, M is outside of the sphere of radius r;
       i.e. x > r,  y > r,  z > r;
       for the most part x>>r,y>>r,z>r;
       thus making all of the angles acute.

Find the equations of the location of M:

   Mx=f(r, Angle AMB, Angle AMC, Angle AMD, Angle BMC, Angle BMD, Angle
CMD)
   My=g(r, Angle AMB, Angle AMC, Angle AMD, Angle BMC, Angle BMD, Angle
CMD)
   Mz=h(r, Angle AMB, Angle AMC, Angle AMD, Angle BMC, Angle BMD, Angle
CMD)


Note: If it is more convenient or less ambiguous, D can be moved to another
location on the xy plane.
Note: I believe that this is over specified, I think the point D is not
needed; i.e
   Mx=f(r, Angle AMB, Angle AMC, Angle BMC)
   My=g(r, Angle AMB, Angle AMC, Angle BMC)
   Mz=h(r, Angle AMB, Angle AMC, Angle BMC)

Question clarification by eldenc on Fri 8 Jan 2010 - 4:05 pm UTC:

As a side note,
I am getting the angles around point M by using a WiiMote camera.
The WiMote (in ubuntu linux 'sudo apt-get wmgui') returns the 4 brightest
IR points in its field of view.  I'm assuming that the distance between the
IR points (sqrt((x1-x2)**2+(y1-y2)**2))) is proportional to the angle.
(After ensuring that the pixels are square.)

Is that assertion correct?

I haven't determined the field of view angles, yet.  I should have that
figured out this weekend.

Uclue Researcher Request for clarification by Researcher mathtalk on Fri 8 Jan 2010 - 8:48 pm UTC:

The clarification about the Wiimote IR camera was helpful.  Knowing a
little about the context I think allows me to address your problem more
clearly.

Let me tackle the question you raise in the clarification, about assuming
the angle is proportional to the apparent (pixelized) distance between two
(bright IR) reference points.  The assumption is approximately true for
small angles/short distances, but if you want an accurate computation of
the location of the Wiimote camera, wider angles/longer distances are
better and will quite possibly invalidate that approximation.  Also be
aware that the camera lens may distort angles/distances around the
periphery of its field of view.

        a
       /|
      / |
     /  |
eye *---+
     \  |
      \ |
       \|
        b

Assume that the camera lens (eye) is directed at the midpoint between a and
b.  Then the apparent distance between a and b is proportional to:

   2 sin(mu/2)

for angle mu between the lines of sight to a and b, if the optics are
"flat" in that region.

As the angle mu tends to zero, the above expression is asymptotic to mu (as
can be seen from the Taylor series for sine).

What the constant of proportionality is between apparent distance
(pixelized) and the above amounts to asking what the apparent depth of the
field of view is, i.e. the dotted line "distance" perpendicular to the
segment ab shown above.   As I think you have in mind, an experiment can
work out the constant.

Two more quick and related notes:

First, yes, the angles that M makes with respect to D and the other points
over-specify the problem of locating M.  In principle the angles at M
formed by pairs AB, AC, and BC are sufficient to locate M at one of two
places, symmetric with respect to the xy-plane (containing A,B,C).

Having the over-specified information is not necessarily a drawback, in
that it can allow us to detect inconsistencies in measurements or to "best
fit" M to measurements with small "random" errors.

Second, the accuracy of the computation is impaired by Mx >> r and My >> r.
 Think of the square ABDC as the "baseline" from which M is observed.  The
most accurate positioning happens when M lies over the square (as deduced
from angle measurements) as one realizes if the limiting case as r
approaches zero (for fixed M) is contemplated.

I hope this "numerical sensitivity" effect will become clearer as we work
through the formulas to a solution for M.  The technical term for locating
an unknown point from angles measured at that vertex is "resection". 
Unfortunately this word has many unrelated meanings and applications, so it
is fairly weak as a search term.  Related terms are "triangulating"
(locating the unknown point from angles at known vertices) and
"trilateration" (locating the unknown point from its distances to known
points).

[Three Point Resection Problem (in 2D)]
http://www.ferris.edu/faculty/burtchr/sure215/notes/resection.pdf

In three dimensions the locus of points M forming a specified positive
angle AMB with known points A.B is a surface of revolution about the axis
passing through A and B.  The case where AMB is a right angle is
particularly nice -- the surface is a sphere with diameter AB.

In theory intersecting two closed surfaces produces one or more closed
curves (e.g. two spheres will intersect in a circle, a point, or not at
all), and intersecting a third surface restricts the possibilities to a
finite number of points (as a circle will intersect a sphere twice, once,
or not at all).

I will ask you to clarify if you are looking more for a mathematical
formulation or a programming approach to solving this.

regards, mathtalk

Question clarification by eldenc on Fri 8 Jan 2010 - 11:28 pm UTC:

I looked at the reference, but unfortunately my last Linear Algebra class
was 14 years ago so I'm a bit slow, I figured I should clarify prior to
understanding the entire text.

Yes the desired format of the answer is C code. (I should be able to handle
the conversion between the trig formula and C code, but if your
offering...(not required) :)

struct Point {float x; float y;};
Point p[4]; //p[0]=A, p[1]=B, etc....

After a little reflection, I exaggerated about the x>>r, sort'of.

I'm flying an RC model plane based on GPS.  Great for flying...not so good
for landing (~2 football fields are required to deal with the GPS altitude
error, which can frequently be up to 10m, unless your willing to land hard)
 
So I think the numerical granularity issues will dissolve away since in the
beginning where the Wii Error is the greatest, far away, I have lots of
error to play with; not causing any issues.  As I approach the landing site
(d,d,0) the angles between the points will increase, thus reducing my
error. To stay in the field of view of the Wii (~70 degrees) this may be
more like (2d,2d,0).

My goal is to put the sensor though an imaginary 2' by 2' box (at roughly
25mph) using 3 or 4 car headlights with r=10'.
FYI: The WiiMote IR camera can report at a 5ms clip, maybe faster (I
haven't pushed it).

Question clarification by eldenc on Sat 9 Jan 2010 - 1:08 am UTC:

Initial development, I plan on comparing the GPS to my Wii Position as a
sanity check.

Then use the Wii data to make me fly on the glide slope, a ray from the
landing site into the sky usually at about 3 degrees.  In my case, the
projection of this ray onto the xy plane will follow x=y.

Uclue Researcher Request for clarification by Researcher mathtalk on Sat 9 Jan 2010 - 7:12 am UTC:

Do you have a method of actually distinguishing A,B,C,D in the camera's
field of view?  That is, mathematically you want to determine the camera's
position from the angles subtended by AB, AC, etc. knowing the locations of
A,B,C,D.  But how do you know which pair of points is being observed in the
camera's view?

I'm imagining that you could have LED's that flash at different rates or
perhaps in varying combinations.


regards, mathtalk

Question clarification by eldenc on Sat 9 Jan 2010 - 3:11 pm UTC:

Man you keep late hours!
Unfortunately, I don't have LEDs that are bright enough (I would need a
board of several hundred, which I may do later); and the incandescents that
are bright enough (and broad banded into the IR) could only be flashed as a
1 second rate or slower, way too slow; Xeon,Neon, etc are at the wrong
frequency range. So I'm using a  geometric solution. I know:
a) The camera will remain level and pointing at the origin to withing
+/-30degrees (pitch/roll/yaw) (from my primary guidance)
b) The camera is constrained to the positive quadrant
With that I can sort on y yielding p0=A, p3=D, B<->C=p[1|2].
Now sort p[1,2] on x p[1]=B and p[2]=C
Yes, this works in code on the plane (in the 'lab' anyway)

As to the format of the answer, I'm more awake now, I think trig functions
for
   Mx=f(r, Angle AMB, Angle AMC, Angle BMC)
   My=g(r, Angle AMB, Angle AMC, Angle BMC)
   Mz=h(r, Angle AMB, Angle AMC, Angle BMC)
would be great.
Additionally, if your willing, Matrix notation for allowing me to move the
points around and how it is derived will be really useful later.

Question clarification by eldenc on Sat 9 Jan 2010 - 3:25 pm UTC:

The x and y for the sort are the pixel xy, not the world reference.
For Your Amusement:  http://paparazzi.enac.fr/wiki/User:EldenC

Question clarification by eldenc on Sat 9 Jan 2010 - 6:37 pm UTC:

Ha, While I was taking a shower I realized that you were going to chid me
that if the camera is on the xz plane and I am tilted then point B would
windup with a pixelized y value that is greater than point A.  Yes that
would be true.  But my projected course on the xy plane is close (+/-10m)
to x=y, so on the real system my lame sort algorithm does work. So you can
assume that I know which point is A, B, C (and maybe D); thus I know AMB,
AMC, and BMC.

Each angle and the corresponding segment length should define an ellipsoid.
So I should be able to obtain intersections of the 2 axis aligned
ellipsoids (defined by AB and Angle AMB; AC and Angle AMC) and the
non-aligned ellipsoid (BC and Angle BMC) to obtain 4(8?) answers.  Then
throw away all answers but the one in the +,+,+ quadrant.

Looking at 
http://en.wikipedia.org/wiki/Ellipsoid
So, I would guess that I need an equation for each ellipsoid in the form of

T(x)Ax=1....then solve the 3 equations....

Question clarification by eldenc on Sat 9 Jan 2010 - 7:03 pm UTC:

FYI: I found a paper that looks about right...but there purchasing
mechanism is broken!
http://cat.inist.fr/?aModele=afficheN&cpsidt=15265349

Uclue Researcher Request for clarification by Researcher mathtalk on Sun 10 Jan 2010 - 4:36 am UTC:

That abstract does look promising for solving the 3D resection problem.  As
I understand, they propose to use resultants to eliminate all but one
variable from a system of multivariate polynomials, then use numerical root
finding on the remaining univariate polynomial.  I suspect the numerical
solution directly of the multivariate system will prove stable and
accurate, but I'm concerned that the solution will suffer from sampling
errors (pixelization) from the camera measurements.

The surfaces generated by the angles and line segments are not ellipsoids,
but that's a good guess.  In two dimensions the locus of points consists of
two branches symmetric wrt the line segment and mutually terminating at the
endpoints of the line segment, and each branch is a circular arc.  However
only in the case of a right angle do the arcs join to form a surface of
rotation that is an ellipsoid (sphere, actually).

Recall the theorem from high school geometry that an interior angle of a
circle has measure half the central angular measurement of the circular arc
cut off by that angle.  A picture is here:

[Angles Within a Circle]
http://www.algebralab.org/lessons/lesson.aspx?file=geometry_interiorangles.xml
(see under "interior angle")

Think of the angle AMB inscribed in a circle, so that AB is a chord and M a
point varying along the circular arc between A and B.  Reflect that part of
the circle through line segment AB and you have both branches of the locus
of points where the angle AMB is a fixed value.  Rotating these branches
(or one of them) around AB produces the locus of points in 3D.


regards, mathtalk

Question clarification by eldenc on Mon 11 Jan 2010 - 7:01 am UTC:

I drew a Google Sketch Up of the problem using your algebra reference,
taking a sample location...but I haven't figured out how to connect the
circles yet.
http://eldenc.tripod.com/a3dLocationFrom3Angles3Pts.skp
(Is there a way to attach files in this clarify section?)
Note that the circles are not accurately sized or placed.

Uclue Researcher Request for clarification by Researcher mathtalk on Mon 11 Jan 2010 - 7:05 am UTC:

As an update, I've begun my own write-up of the math and coding for such
problems.  Also I located a book in the local university library that seems
to collect a lot of related research on the "orientation" problem for
cameras (Gruen and Huang, 2001).  It's a fairly expensive book, so we're in
luck to find a borrowable copy.

The symmetry of the square of observed points allows for certain shortcuts
in the 3D resection problem.  In addition my answer will cover the 2D
resection problem and a numerical method for a general configuration of
points in 3D.

regards, mathtalk

Question clarification by eldenc on Mon 11 Jan 2010 - 7:56 am UTC:

If you choose to look at this file, I used several layers that you may want
to turn on and off. because its getting a bit cluttered.

I'm not sure I understand where to draw the circles.  I chose to place the
circles such that M and its line segment points (AB for the first one) are
on the circumference of the circle. ... but that means that I do not know
anything about the locations of the center of the circles.  It would seem
better to place the circles such that M is the center, but I don't think
that's possible.

Question clarification by eldenc on Mon 11 Jan 2010 - 8:04 am UTC:

Cool! FYI: I posted while you where posting so disregard the previous
clarifications

Uclue Researcher Request for clarification by Researcher mathtalk on Mon 11 Jan 2010 - 2:46 pm UTC:

There's an interesting journal article from the European Space Agency
here:

[Videogrammetry Applied to Environmental Testing for Space Programmes
  by P. Baussart and A. Meurat (2001)]
http://adsabs.harvard.edu/full/2001ESASP.467...43B

It's focus (no pun intended) is on stereogrammatic measurements (two
cameras), but see the "second" section 2 for discussion of "spatial
resection" and many of the issues (accuracy with acute angles, using
overdetermined equations) which arise even with a single camera.

See especially Fig. 7 for a symmetric four point configuration like you've
proposed.


regards, mathtalk

Question clarification by eldenc on Mon 11 Jan 2010 - 5:55 pm UTC:

Yes that looks about right.

a couple of other resources suggested by a friend this morning (I haven't
had time to look into them yet) are 

OpenCV (Open Camera vision)
http://opencv.willowgarage.com/wiki/Welcome

and SLAM (Simultaneous localization and mapping)
http://www.google.com/url?sa=t&source=web&ct=res&cd=5&ved=0CBkQFjAE&url=http%3A%2F%2Fweb.mit.edu%2F16.412j%2Fwww%2Fhtml%2Flectures%2FL3_Introduction%2520to%2520SLAM.pdf&ei=s2BLS7PVAo_0sgPx47Vu&usg=AFQjCNG-JMH1YuJ2Tg8Y25mOB8vOnwA0BA

Uclue Researcher 4 stars Answer by Researcher mathtalk on Sun 17 Jan 2010 - 7:50 pm UTC:

The problem posed here is to find the location:



given the angles at M subtended by line segments between known
points A,B,C,D:






where r > 0.

Methods for solving such "spatial resection" problem are by and
large "direct" or "indirect" (iterative) algorithms.  Direct
methods provide exact solutions after a fixed number of steps,
while indirect methods repetitively improve an approximate
solution until the desired accuracy is reached.

The first known direct solution was given by German mathematician
Grunert in 1841. [Lagrange had given an indirect solution in 1795.]
We will present Grunert's method using three known points, with the
proposal to use a fourth point to decide which among the resulting 
candidates is the correct solution.  After the general method is
stated, we interpolate remarks about how this specializes to the
specific configuration A,B,C,D given above.

Our choice of Grunert's method was informed by a paper "Analysis
and Solutions of The Three Point Perspective Pose Estimation
Problem" by Haralick, Lee, Ottenberg and Nölle [Proc. IEEE Conf.
on Computer Vision and Pattern Recognition, p.590-598 (1991)].
Six direct methods are compared for accuracy when implemented
in single- and double-precision arithmetic.  Their conclusions
put Grunert's method as second-best and show it should be quite
satisfactory for present purposes if double-precision is used.

*  *  *  *  *  *  *  *  *

Grunert's method starts by finding lengths s_A,s_B,s_C of the
unknown tetrahedral edges AM,BM,CM.  This phase is called the
"distance problem".  From those lengths we then locate M, a
phase known as the "bogenschnitt" (bow-shock) or "ranging
problem".

Let a,b,c be the side lengths of BC,AC,AB respectively.  Let
µ_a, µ_b, µ_c be the _cosines_ of the corresonding angles at
M subtended by these three sides.  The unknown point M forms
a tetrahedron with opposing face ABC.  It turns out the angles
appear in the distance problem only through their cosines.

Distance Problem
================

Grunert based a polynomial system on the law of cosines:





for each triangular face meeting at M.  With three quadratic
equations in three unknowns, one expects up to eight isolated
solutions.

In this case we can see that any solutions will pair up in a
symmetry through the origin.  If s_A,s_B,s_C is a solution,
then so is -s_A,-s_B,-s_C.  Therefore we will have at most 
four "physical" solutions to choose from.

Observe that the left-hand sides above are homogeneous of
degree 2 in the unknowns.  Let multipliers u,v be defined:



Then after substituting in (1)-(3) and dividing both sides
by s_A^2:





Equating first and last pairs of these expressions:




Equation (6) may be used to express u^2 thusly:



Substituting this in equation (7) gives u as a rational expression in v:



where t = (a^2 - c^2)/b^2.

If this expression for u is substituted back into (6), clearing
denominators gives a fourth degree polynomial equation in v:



Any positive real root for v in (9) may be substituted in (8) to give
u and in (5b) to give s_A.  Accordingly from (4) we find s_B and s_C.
Although solving quartic polynomials in closed form is a possibility
(Cardano/Ferrari,1545), such direct methods involve complex arithmetic
(even for finding real roots) and a large number of steps.  Accordingly
an indirect method would be a better match to your project needs, a
topic we can discuss later in conjunction with other implementation
details.  (See caveat below about "singular" configurations.)

Note that for our specific coordinates of A,B,C, we have a = r sqrt(2)
and b = c = r.  With this choice (6) and (7) both describe hyperbolas,
and the constant t = 1, reducing the numerator in (8) to first degree.
Nevertheless the resulting polynomial equation (9) is still quartic.

Specializing the discussion to points A,B,C being vertices of the
isoceles right triangle (0,0,0),(r,0,0),(0,r,0) gives a^2 = 2r^2 and
b^2 = c^2 = r^2.  Thus (8) becomes u = (µ_b v - 1)/(µ_a v - µ_c),
which in (6) yields for (9):







One caveat affects both the general and specialized problems.  If
µ_a v = µ_c, then our expression (8) for u involves division by zero.
When the quantities are nearly equal, cancellation affects the error
magnitude.  So we need to beware "singular" configurations in which
unknown v = s_C/s_A approximates the known µ_c/µ_a.

Ranging Problem
===============

For each positive real solution s_A,s_B,s_C there exists a candidate M.
That is, the distances constrain M to the intersection of three spheres
centered on A,B,C respectively.  Two spheres intersecting in more than
one point intersect in a circle, and such circle lies in a plane whose
equation is quickly deduced from the equations of the spheres.

Indeed consider the intersection of the sphere of radius s_A centered
on A with the sphere of radius s_B centered on B.  The plane containing
their circle of intersection will be perpendicular to line AB, and the
circle will be centered somewhere along line AB (not necessarily at a
point between A and B).

Likewise the spheres centered on A and on C will intersect (if in more
than one point) in a circle lying in a plane perpendicular to line AC.
M must lie in both planes, which are not parallel, so that two of M's
coordinates can be expressed parametrically in terms of the third.
Intersecting that line with any of the three spheres gives two possible
points M, symmetric with respect to the plane containing ABC.

In this case our specific choice of A,B,C makes that computation
especially easy.  A is the origin and B is (r,0,0).  Equations for
the respective spheres are:




    
Subtracting the latter from the former gives the plane:



which implies the value of x_M:



Likewise the intersection of spheres centered on A and C implies:



As we presume that z_M > 0, our final coordinate is:



Distinguish the correct location M
==================================

Finally for each candidate M we check its angles involving point D.
If it is correct, the dot products of (M-D) and (M-A) should be the
product of lengths s_A times s_D times the cosine of the angle at M
subtended by AD, where s_D is the distance from M to D).  With four
coplanar points A,B,C,D there should only be two solutions for M,
symmetric with respect to the plane containing ABDC.  The constraint
z_M > 0 distinguishes the two possibilities in our case.


regards, mathtalk

Uclue Researcher Answer clarification by Researcher mathtalk on Mon 18 Jan 2010 - 2:49 pm UTC:

"In troth, Sirs, I shall not hold you much longer, for I will only say thus
to you.   That in truth I could have desired some little time longer,
because I would have put then that I have said in a little more order, and
a little better digested than I have done.   And, therefore, I hope that
you will excuse me."

 - from remarks by King Charles I, Jan. 30, 1648, on the occasion of his
beheading

ERRATUM
=======

There's nothing better than a worked example to discover errors in one's
formulas!  Here I have made a sign error in the coefficient K_3 above,
which should have been:



The example I writing up is for an isoceles right triangle with r = 1 and:



which I hope will illustrate Grunert's method and the pitfalls of
measurement errors for the angles.  I hope there are no further errors of
formulation to be discovered, but we may see...

regards, mathtalk

Comment by eldenc on Wed 20 Jan 2010 - 5:02 am UTC:

Well, now I'm depressed I tried to put
http://en.wikipedia.org/wiki/Quartic_function  Ferrari's method into a
function (I'll need it in C but I thought Python may be easier to read)..
I'm not thinking that this is correct since there can be up to 64 resultant
values....did you have better math for the roots?
(Why is this text box so small, not even 80 chars much less 132?
01234567890123456789012345678901234567890123456789012345678901234567890123456789)

def getRootsBiQuad (A,B,C,D,E):
    '''Given the quartic equation
          A x^4 + B x^3 + C x^2 + D x + E = 0
    its solution can be found by means of the following calculations
    sourced from http://en.wikipedia.org/wiki/Quartic_function
    Ferrari's method'''
    alpha = (-                                       ((3*B**2)/(8*A**2)) +
(C/A) )
    beta  = (                        (  B**3/( 8*A**3)) - (B*C/(2*A**2)) +
(D/A) )
    gamma = (- (3*B**4/(256*A**4)) + (C*B**2/(16*A**3)) - (B*D/(4*A**2)) +
(E/A) )

    x=[]
    if beta==0:  ###its floating point beta will never be 0! what is the
tolerance?
        t1=-(B/4*A)
        t3=sqrt(alpha**2-4*gamma)
        x.append(t1+sqrt((-alpha+t3)/2))
        x.append(t1+sqrt((-alpha-t3)/2))
        x.append(t1-sqrt((-alpha+t3)/2))
        x.append(t1-sqrt((-alpha-t3)/2))
        return x
    else:  #Otherwise, continue with

        P = - (alpha**2/12)  - gamma
        Q = - (alpha**3/108) + (alpha*gamma/3) - (beta**2/8)
        t1=sqrt((Q**2/4)+(P**3/27))
        t2=-(Q/2)
        R1 = t2 + t1
        R2 = t2 - t1 
    
        #(either sign of the square root will do)???? what does this mean?
        ###Do I get to chose the one that's positive to avoid the
pow(-,0.3333)?
        ### http://docs.python.org/library/math.html
        ### If both x and y are finite, x is negative, and y is not an
integer then pow(x, y) is undefined, and raises ValueError.
        U1 = pow( R,1/3) 
        U2 = pow(-R,1/3) 
        #(there are 3 complex roots, any one of them will do)
    
        t11=-(5/6)*alpha + U1
        t21=-(5/6)*alpha + U2
        pu1=-P/(3*U1)
        pu2=-P/(3*U2)
        y=[]
        y.append(t11 - pu1)
        y.append(t11 - pu2)
        y.append(t11 - pu1)
        y.append(t21 - pu1)
    
        W=[]
        for yy in y:
            W.append(sqrt(alpha + 2*yy))
        #####W is 4 different answers
    
        num=[] ##as in numerator
        for yy in y:
            yyy=3*alpha+2*yy
            for w in W:
                b2w=(2*beta/w)
                num.append( +w+sqrt(-(yyy+b2w)) )
                num.append( +w+sqrt(-(yyy-b2w)) )
                num.append( +w-sqrt(-(yyy+b2w)) )
                num.append( +w-sqrt(-(yyy-b2w)) )
                num.append( -w+sqrt(-(yyy+b2w)) )
                num.append( -w+sqrt(-(yyy-b2w)) )
                num.append( -w-sqrt(-(yyy+b2w)) )
                num.append( -w-sqrt(-(yyy-b2w)) )
        
        t1=-(B/4*A)
        for n in num:
            x.append(t1+n/2)
    
    return x ########???? This is around 8*4*4=64 answers and most of them
are complex!

Uclue Researcher Answer clarification by Researcher mathtalk on Wed 20 Jan 2010 - 2:30 pm UTC:

Yes, there are better ways to tackle the roots of the quartic.

The quadratic formula is quite practical, and I've done a Python
implementation of the solution by radicals for a cubic (Cardano):

[Q: for mathtalk-ga only: Need more help with cubic equations]
http://answers.google.com/answers/threadview/id/441538.html

but I've never tried to do Ferrari's formula for the quartic.  I believe
that it would require Cardano's method as a subroutine to solve the
auxiliary cubic.

My thought is to tackle the positive roots of the quartic by numerical
approximation.  The general approach is a "divide-and-conquer" technique of
forming intervals that isolate the positive roots, then using some
"standard" root finding methods like bisection/secant/Newton/Laguerre.

For isolating the roots of a polynomial it can be observed that between two
real roots there must be a root of its derivative.  That is, if f(z) = f(w)
= 0 for z < w, there must exist t strictly between z and w s.t. f'(t) = 0
by the Mean Value Theorem.  Thus the roots of f' separate the roots of f,
and the roots of f" separate the roots of f', when the roots are all
distinct.

Now since f" will be a quadratic in our case, it is easily solved.  The
cubic f' must have at least one real root, and if f has four distinct real
roots then f' will actually have three real roots by the above.  Once one
of the real roots of f' is found, it can be factored out (deflation)
leaving a quadratic polynomial to solve.  While deflation can introduce
some rounding errors in the remaining roots, that is not a terrible thing
here because we want the roots of f' only for producing the isolating
intervals for roots of f, and modest inaccuracy of f' roots will not change
that result.

The implementation of root finding methods, even for (general) polynomials,
is a tricky topic that has been picked over by many bright people before
us.  So we should try to take advantage of their work and only reinvent the
wheel if necessary.  I'll look first at the Quartic Solver written in C by
Andrew Steiner linked here (GPL licensing):

[GSL - GNU Scientific Library]
http://www.gnu.org/software/gsl/

Look for the Quartic link about two-thirds of the way down the page.

regards, mathtalk

Uclue Researcher Answer clarification by Researcher mathtalk on Wed 20 Jan 2010 - 11:51 pm UTC:

At a glance the code linked above contains two C programs, solve_quartic.c
and zsolve_quartic.c.  The latter finds all roots, where the former is
"simplified" to finding only real roots of a quartic polynomial.

So solve_quartic.c definitely seems to be worth a closer look and a bit of
testing on my example problem.

regards, mathtalk

Comment by eldenc on Sun 24 Jan 2010 - 9:47 am UTC:

My code no worky :-(
All of the point collections given to calulatePostionsFromAngles(...)
should have returned x, y, and z values that are greater than 1 since they
are all greater than (about 5x) the size of r (r=AB=AC).

Did you say that you had worked an example?
If you have the intermediate answers to that example, I would like to plug
them into the code below to see if my error is in the transformation that I
am feeding the angles into the function, or I mis-adapted your math into
the C-code.  (If you wish to execute my code, then see the notes near the
top of the file.)  PS. To give you credit in the code that I eventually
check-in as something more exacting than mathtalk, then send me an email.
A sample of it's out put is:
=============================================
For points:
  A=(211,369)
  B=(70,396)
  C=(292,481)
  D=(155,502)
    Given the angles about M
a_radians=0.340091,b_radians=0.197747,c_radians=0.205388
                                  (u_a=0.942724),    (u_b=0.980512),   
(u_c=0.978982)
        the quartic problem:      v**4 + -4.03794v**3 + 6.02756v**2 +
-4.09991v**1 + 1.0316 = 0
        numsolutions=2,  1234=0.597214,1.70468,0,0
        v[0]=0.597214  u[0]=0.996276
        v[1]=1.70468  u[1]=1.0691
        (sa,sb,sc)[0]=(0.227407,0.22656,0.135811)
        (sa,sb,sc)[1]=(0.612728,0.655066,1.0445)
    M(x,y,z)[0]=(1.00085,1.0916,nan)
    M(x,y,z)[1]=(0.957662,0.568224,nan)
M=(0,0,0)
=====================================================

=============================================================
/*
 * $Id: whereAmI.c 3326 2010-01-23 08:05:29Z eldenc $
 *  
 * Copyright (C) 2010 Elden Crom, uclue.com mathtalk
 *
 * This file is (will be) part of paparazzi.
 *
 * paparazzi is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version.
 *
 * paparazzi is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with paparazzi; see the file COPYING.  If not, write to
 * the Free Software Foundation, 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA. 
 *
 */


//////////////////////////////////////////////////////////////////////////
// for my purposes I pulled in gsl_poly_solve_quartic
// and gsl_poly_solve_quadratic from
// http://www.network-theory.co.uk/download/gslextras/Quartic/
// and
// cvs -d :pserver:anonymous@pserver.git.sv.gnu.org:/gsl.git checkout -d
gsl HEAD
// respectively, removed the includes except
// #include <math.h> and added 
// #define GSL_MAX(a,b) ((a) > (b) ? (a) : (b))
// 
// The compile via 
// gcc whereAmI.c solve_quartic.c solve_quadratic.c -lm
//////////////////////////////////////////////////////////////////////////

#include <stdio.h>
#include <math.h>

/* solve_quartic.c - finds the real roots of 
 *  x^4 + a x^3 + b x^2 + c x + d = 0
 */
int
gsl_poly_solve_quartic (double a, double b, double c, double d,
                        double *x0, double *x1, double *x2, double *x3);

#define TEST_WHEREAMI
#ifdef TEST_WHEREAMI
  #define dprintf(args...) printf(args)
  #define dprintf_loop(loop_max,args...) {unsigned int
i=0;for(i=0;i<loop_max;i++){printf(args);}}
  int testTolf64(const char *msg,double  act,double  exp, double 
tol_pct);
  void report();
#else
  #define dprintf(args...) ;
#endif //TEST_WHEREAMI


//////////////////////////////////////////////////////////////////////////////
// The Function preforms "direct spatial resection" to 
// transform the angles into x,y,z co-ordinates of an unknown point M.
// The units of x, y, and z are r.
//
//Geometry: Find a 3d location based on 6 angles and 1 length
//(4PointsAndACamera)
//
//Let A, B, C, and D be four points on the xy plane in a 3 Dimensional
//Cartesian space.
//Let M represent a point of unknown position in the positive xyz
quadrant.
//
//Given that:
//
//   A is as the origin   (0,0,0)
//   B is on the x axis   (r,0,0)
//   C is on the y axis   (0,r,0)
//   where r > 0
//
//   The angles AMB, AMC, and BMC are supplied.
// 
//   Looking strait down the Z-axis A,B and C appear as
//   A----C--- positive Y-Axis
//   |
//   |
//   B
//   |
//   positive X-Axis
// 
// 
// Note: In most applications the user will scale each co-ordinate by r
// in order to obtain the real world units for M(x,y,z).
// 
//The function returns upto 4 possible solutions into 
//the arrays aMx[4],double aMy[4],double aMz[4]
// @param a_radians --- the angle 
// @return the number of possible solutions
int calulatePostionsFromAngles(double a_radians    ,double b_radians   
,double c_radians, 
                               double *aMx, double *aMy, double *aMz){
    double u_a=cos(a_radians);
    double u_b=cos(b_radians);
    double u_c=cos(c_radians);
    dprintf("    Given the angles about M
a_radians=%g,b_radians=%g,c_radians=%g\n",a_radians,b_radians,c_radians);
    dprintf("                                  (u_a=%g),    (u_b=%g),   
(u_c=%g)\n",u_a,u_b,u_c);
    double k0,k1,k2,k3,k4;
    //from http://uclue.com/?xq=3601&form=comment#form by mathtalk
    //These coefficients correspond to A=(0
    k0=2.0*u_c*u_c-1.0;
    k1=-2.0*(u_a*u_c+u_b*(2.0*u_c*u_c-1.0));
    k2=u_a*u_a+6.0*u_a*u_b*u_c-u_b*u_b;
    k3=-2.0*u_a*(u_c+u_a*u_b);//the corrected one
    k4=u_a*u_a;

    double a,b,c,d;
    a= k3/k4;  //gsl_poly_solve_quartic expects the coefficient of x**4 to
be 1
    b= k2/k4;  //so divide each by k4
    c= k1/k4;  
    d= k0/k4;

    double v[4]={0,0,0,0};
    int numsolutions;
    //gsl_poly_solve_quartic expects x^4 + a x^3 + b x^2 + c x + d = 0
    numsolutions=gsl_poly_solve_quartic(a,b,c,d,&v[0],&v[1],&v[2],&v[3]);
    dprintf("        the quartic problem:      v**4 + %gv**3 + %gv**2 +
%gv**1 + %g = 0\n",a,b,c,d);
    dprintf("        numsolutions=%d, 
1234=%g,%g,%g,%g\n",numsolutions,v[0],v[1],v[2],v[3]);
    //ps these agree with a quartic web calculator I found at 
    //   http://www.freewebs.com/brianjs/ultimateequationsolver.htm

    //Now that we have solved the quartic determine the lengths of the
sides
    double u[4]={0,0,0,0};
    //double t;
    //double r=1;
    ////A   B   AB=r;AC=r;CB=sqrt(AB*AB+AC*AC)
    ////
    ////C
    //b=r;  //AC
    //c=r;  //AB
    //a=sqrt(c*c+b*b); //BC
    //t=(a*a-c*c)/(b*b);   Our Special Case t=(r**2+r**2-r**2)/r**2=1
    int i;
    for(i=0;i<numsolutions;i++){
        //Equation 8 from http://uclue.com/?xq=3601&form=comment#form by
mathtalk
        //u[i]=(  (t-1.0)*v[i]*v[i] - 2.0*t*u_b*v[i] + (t+1.0)  ) /
        //            (2.0*u_c-u_a*v[i]);
        //Our special case (t=1)
        u[i]=( u_b*v[i] - 1.0 ) / ( u_a*v[i]-u_c );
    }
    dprintf_loop(numsolutions,"        v[%d]=%g 
u[%d]=%g\n",i,v[i],i,u[i]);
    double sa[4]={0,0,0,0},
           sb[4]={0,0,0,0},
           sc[4]={0,0,0,0};
    for(i=0;i<numsolutions;i++){
        //Equations 4 and 5 from
http://uclue.com/?xq=3601&form=comment#form by mathtalk
        //sa[i]=( u[i]*u[i]+v[i]*v[i] - 2.0*u_a*u[i]*v[i] ) /
        //                  a*a;
        //specialized for our case a*a=1
        sa[i]=( u[i]*u[i]+v[i]*v[i] - 2.0*u_a*u[i]*v[i] );
        sb[i]=u[i]*sa[i];
        sc[i]=v[i]*sa[i];
    }
    //print out the lengths of the sides
    dprintf_loop(numsolutions,"       
(sa,sb,sc)[%d]=(%g,%g,%g)\n",i,sa[i],sb[i],sc[i]);

    /////now we have up to 4 solutions for the lengths of MA,MB,MC
(sa,sb,sc respectively)
    double Mx[4]={0,0,0,0},
           My[4]={0,0,0,0},
           Mz[4]={0,0,0,0};
    for(i=0;i<numsolutions;i++){
        //Equations 10 and 11 from
http://uclue.com/?xq=3601&form=comment#form by mathtalk
        //Mx[i]=( sa[i]-sb[i]+r*r ) / (2*r);
        //My[i]=( sa[i]-sc[i]+r*r ) / (2*r);
        //specialized for our case (r=1)
        Mx[i]=( sa[i]-sb[i]+1 );
        My[i]=( sa[i]-sc[i]+1 );
        Mz[i]=sqrt(sa[i]*sa[i]-Mx[i]*Mx[i]-My[i]*My[i]);
    }
    //print out the results
    dprintf_loop(numsolutions,"   
M(x,y,z)[%d]=(%g,%g,%g)\n",i,Mx[i],My[i],Mz[i]);
    return numsolutions;
}


double distance(int ax, int ay, int bx, int by){
    int x=ax-bx;
    int y=ay-by;
    return sqrt(x*x+y*y);
}

int calcLocationM(int ax,int ay,
                  int bx,int by,
                  int cx,int cy,
                  int dx,int dy,
                  double *Mx,double *My,double *Mz){
    dprintf("For points:\n  A=(%d,%d)\n  B=(%d,%d)\n  C=(%d,%d)\n 
D=(%d,%d)\n",ax,ay,bx,by,cx,cy,dx,dy);
    //this is specific to the Wii Mote Camera
    double radians_per_pixel=0.00143066; //atan(12.5 cm /54.0 cm)/159
pixels
    //angles
    double a_radians=distance(bx,by,cx,cy)*radians_per_pixel; //the angle
subtended by bc from 3d point M
    double b_radians=distance(ax,ay,cx,cy)*radians_per_pixel;
    double c_radians=distance(ax,ay,bx,by)*radians_per_pixel;
    //the full complement of results (all but one are invalid)
    double aMx[4],aMy[4],aMz[4];
    int i;
    for(i=0;i<4;i++) {aMx[i]=aMy[i]=aMz[i]=0;}
    int
numRes=calulatePostionsFromAngles(a_radians,b_radians,c_radians,aMx,aMy,aMz);
    //////// Distinguish the correct location M from the possible
solutions
    double ud=distance(ax,ay,bx,by)*radians_per_pixel;
    //int i;
    //int found1;
    //for(i=0;i<numRes;i++){
    //    ????????????????????????????????????????
    //    //if(aMz <= 0) continue;//redundant...with sqrt that z was
caculated for
    //    //So I need to do calulatePostionsFromAngles() again to determine
s_D? 
    //}
    *Mx=aMx[0];
    *My=aMy[0];
    *Mz=aMz[0];
    dprintf("M=(%g,%g,%g)\n\n",*Mx,*My,*Mz);
}



#ifdef TEST_WHEREAMI
struct TestCases2dPoints {
    int ax,ay, 
        bx,by, 
        cx,cy, 
        dx,dy;
    double Mx,My,Mz;
};
int main(int argc,char**argv){        
    struct TestCases2dPoints tc[]={
         // a                b                 c                d          
           Mx,My,Mz (r=5.5 in)
{485.000,607.000,   344.000,661.000,  617.000,690.000,   472.000,736.000,
/*endpts*/5.078,5.078,3.273},// x=y R=39.5,z=18
//////Roll, pitch, heading change same pos
{656.000,520.000,   548.000,600.000,  780.000,588.000,   667.000,662.000,
/*endpts*/5.206,5.206,5.273},// x=y R=40.5,z=29
{656.000,520.000,   548.000,600.000,  780.000,588.000,   667.000,662.000,
/*endpts*/5.206,5.206,5.273},// x=y R=40.5,z=29
{547.000,363.000,   434.000,438.000,  662.000,438.000,   546.000,505.000,
/*endpts*/5.206,5.206,5.273},// x=y R=40.5,z=29 (same diff pitch)
{522.000,304.000,   391.000,323.000,  593.000,419.000,   461.000,428.000,
/*endpts*/5.206,5.206,5.273},// x=y R=40.5,z=29 (same diff roll)
{515.000,412.000,   394.000,473.000,  620.000,500.000,   499.000,552.000,
/*endpts*/5.206,5.206,5.273},// x=y R=40.5,z=29 (remove ruler)        
{803.000,539.000,   694.000,627.000,  934.000,604.000,   819.000,683.000,
/*endpts*/5.206,5.206,5.273},//heading
{211.000,369.000,    70.000,396.000,  292.000,481.000,   155.000,502.000,
/*endpts*/5.206,5.206,5.273} //heading
};
    int numRes,i;
    for(i=0;i<sizeof(tc)/sizeof(struct TestCases2dPoints);i++){
        double Mx,My,Mz;
        numRes=calcLocationM(tc[i].ax,tc[i].ay,
                             tc[i].bx,tc[i].by,
                             tc[i].cx,tc[i].cy,
                             tc[i].dx,tc[i].dy,
                             &Mx,&My,&Mz);
        //testTolf64("Check value of Mx",Mx,tc[i].Mx,0.5);
        //testTolf64("Check value of My",Mx,tc[i].My,0.5);
        //testTolf64("Check value of Mz",Mx,tc[i].Mz,0.5);
    }
    report();
}

//struct TestCasesAngles {
//    double a_radians,b_radians,c_radians;
//    double Mx[4],My[4],Mz[4];
//};
//int main(int argc,char**argv){
//    struct TestCasesAngles tc[]={{  1.000,  2.000,  3.000,{},{},{} },
//                                 {  1.000,  2.000,  3.000,{},{},{} }
//                                };
//    double aMx[4],aMy[4],aMz[4];
//    int i;
//    for(i=0;i<4;i++) {aMx[i]=aMy[i]=aMz[i]=0;}
//    int numRes,i;
//    for(i=0;i<sizeof(tc)/sizeof(struct TestCasesAngles);i++){
//       
numRes=calulatePostionsFromAngles(tc[i].a_radians,tc[i].b_radians,tc[i].c_radians
//                                          aMx,aMy,aMz);
//    }
//}
////////////////////////////////The test harness
int num_tests=0;
int num_pass=0;
int num_fail=0;
int testTolf64(const char *msg,double  act,double  exp, double  tol_pct){
    double delta=exp-act;
    double tol = abs((tol_pct/100.0)*exp);
	int passed=0;
    num_tests++;
    if (fabs(delta) < tol){
        num_pass++;
        passed = 1;
        printf("PASSED ");
    } else {
        num_fail++;
        printf("FAILED ");
    }
	printf("%s\n\t  actual=%f\texpected=%f\ttolerance:
+/-%f\n",msg,act,exp,tol);
	printf("\t\t  delta = %f\n",delta);
    return passed;
}
void report(){
     printf("  summary:\n");
     printf("  # of tests complete = %d\n",(int)num_tests);
     printf("  # of tests failed   = %d\n",(int)num_fail );
     printf("  # of tests passes   = %d\n",(int)num_pass );
     if(num_pass > 0 && num_pass==num_tests){
         printf("OverAll results for test: PASSED -- yeah\n");
     }else{
         printf("OverAll results for test: FAILED\n");
     }     
     num_tests=num_pass=num_fail=0;//zeroing test variables
}
#endif //TEST_WHEREAMI

Uclue Researcher Answer clarification by Researcher mathtalk on Sun 24 Jan 2010 - 3:22 pm UTC:

The first thing I see is that A,B,C,D no longer form a square.  The quartic
formula I gave for v was specialized to the case when A,B,C are
(0,0,0),(r,0,0),(0,r,0).  [D hasn't entered into the problem formulation at
that stage.]

I can give you the quartic for three general points A,B,C, and you will see
that the coefficients depend on the side lengths c=length(AB),
b=length(AC), a=length(BC).  This dependence "disappeared" in the
expressions for K_i, i=0,..4 above because I'd plugged in their values in
terms of r, and in fact the dependence is only on the ratios of (squares
of) the lengths a,b,c.

The algebra is daunting enough even in the simplified case that I needed
Maxima (the open source CAS) to keep me straight, and even then I failed to
catch one sign error.  So I'll definitely have to rely on a symbolic
calculator for the general equation.

Here is my example and its intermediate results:

When r = 1 and M = (1/4,3/4,4), the cosines of angles are:

µ_a = cos(Angle BMC) = (M-B).(M-C)/(|MB|*|MC|) = 0.940274968

µ_b = cos(Angle AMC) = (M-A).(M-C)/(|MA|*|MC|) = 0.969578653

µ_c = cos(Angle AMB) = (M-A).(M-B)/(|MA|*|MB|) = 0.940274968

and consequently my quartic has coefficients:

K_4 =  0.884117015
K_3 = -3.539472195
K_2 =  5.310273647
K_1 = -3.538568001
K_0 =  0.883650733

There are four distinct real roots, all reasonably close to 1.  The root v
we are interested in is v = 0.984847609, which corresponds by (8) to:

u = 1.014926198

and thus by (5b) and (4) to:

s_A = 4.077376608
s_B = 4.138236339
s_C = 4.015594601

The coordinates of M can then be computed from (10),(11),(12):

x_M = 0.25
y_M = 0.75
z_M = 4.00

regards, mathtalk

Uclue Researcher Answer clarification by Researcher mathtalk on Sun 24 Jan 2010 - 4:15 pm UTC:

Let me describe my own "test harness" a bit further, since I don't find C
programming "agile" enough for exploratory work.

I used an Excel spreadsheet for most formulas (OpenOffice Calc would be
equal to the task) and to solve the quartic equations:

[Quartic Root Calculator by Stephen R. Schmitt]
http://home.att.net/~srschmitt/script_quartic.html

with scripting enabled and the "No rounding" option/radio button.

Mr. Schmitt's Javascript code, which is visible in a browser through
View|Source, uses the Lin-Bairstow algorithm starting with randomized
guesses.  Because of the nature of the "resection" application, it is not
coincidental that v = s_C/s_A would be close to 1.  If the distance of M
from the three points A,B,C is large in comparison to the intra-triangle
distances a,b,c, then ratios u and v will naturally be about 1.

My point is that we "know" enough about the roots of the quartic to be able
to avoid randomized guesses which might lead to occasional divergence in
root finding.  However with an educated guess about roots, the Lin-Bairstow
algorithm would be an attractive algorithm.  Essentially it would use
Newton-Raphson to factor (in real arithmetic) the quartic into a pair of
(easily solved) quadratic equations.

regards, mathtalk

Comment by eldenc on Sun 24 Jan 2010 - 8:20 pm UTC:

I think the problem happens at the calculations of the K values...
I stripped down the C code to just calculate the K values (below) and this
is what I get:
    Given the angles about M a_radians=  0.347359179000,b_radians= 
0.247292756000,c_radians=  0.347359179000
        u_a=  0.940274967965
        u_b=  0.969578653117
        u_c=  0.940274967965
        k0=  0.768234030764
        k1= -3.257960664417
        k2=  5.087360160632
        k3= -3.482676000707
        k4=  0.884117015382

k4 agrees but the rest do not.  
Is your applications order of precedence not C/Algebra like?
(times before +/-?)
Can you copy and paste the formulas for k... in plain text?

=======================================================
//File justKvals.c
// compile with 'gcc justKvals.c -lm'
// 
#include <stdio.h>
#include <math.h>

#define dprintf(args...) printf(args)

int calulatePostionsFromAngles(double a_radians    
                              ,double b_radians    
                              ,double c_radians 
                              ,double *aMx, double *aMy, double *aMz){
    double u_a=cos(a_radians);
    double u_b=cos(b_radians);
    double u_c=cos(c_radians);
    #define GG "%16.12f"
    dprintf("    Given the angles about M a_radians="GG",b_radians="GG","
            "c_radians="GG"\n",a_radians,b_radians,c_radians);
    double k0,k1,k2,k3,k4;
    //from http://uclue.com/?xq=3601&form=comment#form by mathtalk
    dprintf("        u_a="GG"\n",u_a);
    dprintf("        u_b="GG"\n",u_b);
    dprintf("        u_c="GG"\n",u_c);
    k0=2.0*u_c*u_c-1.0;
    k1=-2.0*(u_a*u_c+u_b*(2.0*u_c*u_c-1.0));
    k2=u_a*u_a+6.0*u_a*u_b*u_c-u_b*u_b;
    k3=-2.0*u_a*(u_c+u_a*u_b);//the corrected one
    k4=u_a*u_a;
    dprintf("        k0="GG"\n",k0);
    dprintf("        k1="GG"\n",k1);
    dprintf("        k2="GG"\n",k2);
    dprintf("        k3="GG"\n",k3);
    dprintf("        k4="GG"\n",k4);
}

struct TestCasesAngles {
    double a_radians,b_radians,c_radians;
    double Mx[4],My[4],Mz[4];
};
int main(int argc,char**argv){
    struct TestCasesAngles tc[]={{  0.347359179,/*u_a=0.940274968*/
                                    0.247292756,/*u_b=0.969578653*/
                                    0.347359179,/*u_c=0.940274968*/  
                                    {},{},{} }
                                //,{  1.000,  2.000,  3.000,{},{},{} }
                                };
    double aMx[4],aMy[4],aMz[4];
    int i,k,numRes;
    for(i=0;i<sizeof(tc)/sizeof(struct TestCasesAngles);i++){
        for(k=0;k<4;k++) {aMx[k]=aMy[k]=aMz[k]=0;}
        numRes=calulatePostionsFromAngles(tc[i].a_radians,
                                          tc[i].b_radians,
                                          tc[i].c_radians,
                                          aMx,aMy,aMz);
    }
}

Uclue Researcher Answer clarification by Researcher mathtalk on Sun 24 Jan 2010 - 9:42 pm UTC:

Sorry, I made a cut-and-paste error when I gave you µ_c.  It should have
not have been identical to µ_a, but instead:

mu_c = 0.970476876

I think that explains the problem.  It certainly explains the difference in
values for K_0.  Here are some plaintext (C syntax?) formulas for the
coefficients:

K_0 = 2*mu_c*mu_c - 1
K_1 = -2*(mu_a*mu_c + mu_b*(2*mu_c*mu_c - 1))
K_2 = mu_a*mu_a + 6*mu_a*mu_b*mu_c - mu_b*mu_b
K_3 = -2*mu_a*(mu_c + mu_a*mu_b)
K_4 = mu_a*mu_a

This includes the sign correction to K_3 posted earlier.

regards, mathtalk

Uclue Researcher Answer clarification by Researcher mathtalk on Sun 24 Jan 2010 - 9:48 pm UTC:

I checked the formulas and they match your code.

-mt

Comment by eldenc on Sun 24 Jan 2010 - 10:56 pm UTC:

getting closer but no cigar yet....

your examples k2 (K_2 =  5.310273647) is off in the second significant
digit wrt mine   (k2  =  5.252565299146). Considering the u_a, u_b and u_c
are the same out to the 8 significant this seems odd.

k2  =  u_a* u_a + 6.0* u_a* u_b* u_c -  u_b* u_b;  //mine (added spaces)
K_2 = mu_a*mu_a + 6  *mu_a*mu_b*mu_c - mu_b*mu_b  //yours (added spaces)

    
Given the angles about M a_radians=  0.347359179000,b_radians= 
0.247292756000,c_radians=  0.243596173000
  ...Force the angles to the example..
        u_a=  0.940274968000
        u_b=  0.969578653000
        u_c=  0.970476876000
        k0=  0.883650733701
        k1= -3.538568003261
        k2=  5.252565298780
        k3= -3.539472196915
        k4=  0.884117015447

Uclue Researcher Answer clarification by Researcher mathtalk on Sun 24 Jan 2010 - 11:18 pm UTC:

You are right about that!  The value for K_2 should be 5.252565295.  My
Excel spreadsheet formula pointed to the wrong cell for the first square in
that expression, getting µ_c^ instead of µ_a^2 for the somewhat larger
result.  I'll redo my quartic solution next as this must change roots v
somewhat.

-mt

Comment by eldenc on Mon 25 Jan 2010 - 1:06 am UTC:

Currently, mine app says....
=======================================================
    Given the angles about M a_radians=  0.347359178898,b_radians= 
0.247292756478,c_radians=  0.243596173163
                                  (u_a=  0.940274968000),    (u_b= 
0.969578653000),    (u_c=  0.970476876000)
        u_a=  0.940274968000
        u_b=  0.969578653000
        u_c=  0.970476876000
        k0=  0.883650733701
        k1= -3.538568003261
        k2=  5.252565298780
        k3= -3.539472196915
        k4=  0.884117015447
        the quartic problem:      v**4 +  -4.003397893122v**3 +  
5.941029532298v**2 +  -4.002375184997v**1 +   0.999472601774 = 0
        numsolutions=2,  v[0..4]=  0.605130619212,  1.651992830452, 
0.000000000000,  0.000000000000
        v[0]=  0.605130619212  u[0]=  1.029367193268
        v[1]=  1.651992830452  u[1]=  1.032403419608
        (sa,sb,sc)[0]=(  0.254382307596,  0.261852801987,  0.153934523312)
        (sa,sb,sc)[1]=(  0.587615875187,  0.606656638959,  0.970737212868)
    M(x,y,z)[0]=(  0.992529505609,  1.100447784284,             nan)
    M(x,y,z)[1]=(  0.980959236228,  0.616878662318,             nan)
=============================================================
The roots agree with those of 
http://www.freewebs.com/brianjs/ultimateequationsolver.htm

Uclue Researcher Answer clarification by Researcher mathtalk on Mon 25 Jan 2010 - 2:40 am UTC:

Okay, I checked my handwritten notes (copied from Maxima on my Linux box)
and the coefficient K_2 does have mu_c^2, not mu_a^2 as the leading term:

K_2 = mu_c*mu_c + 6*mu_a*mu_b*mu_c - mu_b*mu_b

So in the case of the given angles, K_2 = 5.310273647, and the quartic was
correct in having these four real roots:

1.054650618676
1.026262454132
0.984848883367
0.937635936807

Of these the actual v = 0.984848883367 corresponds to M = (0.25,0.75,4.0).

regards, mt

Comment by eldenc on Mon 25 Jan 2010 - 4:48 am UTC:

Yeah, we're close and after fixing a few issues in my code one of the
solutions looks pretty good:
M(x,y,z)[1]=(  0.249999787814,  0.750000060576,  3.999999981443)

now I can kick out M[3] easily (negative length), but I don't know the
length of s_D (it has 4, well 3, possible lengths) so I don't know how to
apply "Distinguish the correct location M"

PS I'm putting a tar file of my current code at
http://eldenc.tripod.com/resection4knowPointsAndAngles.20100124b.tar.gz
(The python's not done yet, so no visuals using a WiiMote yet)
======================= a.out output ==================================
    Given the angles about M a_radians=  0.347359178898,b_radians= 
0.247292756478,c_radians=  0.243596173163
                                  (u_a=  0.940274968000),    (u_b= 
0.969578653000),    (u_c=  0.970476876000)
        u_a=  0.940274968000
        u_b=  0.969578653000
        u_c=  0.970476876000
        k0=  0.883650733701
        k1= -3.538568003261
        k2=  5.310273650183
        k3= -3.539472196915
        k4=  0.884117015447
        the quartic problem:      v**4 +  -4.003397893122v**3 +  
6.006301832678v**2 +  -4.002375184997v**1 +   0.999472601774 = 0
        numsolutions=4,  v[0..4]=  0.937636277934,  0.984847604681, 
1.026264197407,  1.054649813100
        v[0]=  0.937636277934  u[0]=  1.023040340709
        v[1]=  0.984847604681  u[1]=  1.014926211009
        v[2]=  1.026264197407  u[2]=  0.900079053377
        v[3]=  1.054649813100  u[3]=  1.065238180219
        (sa,sb,sc)[0]=(  4.050955774111,  4.144291175346,  3.798323094112)
        (sa,sb,sc)[1]=(  4.077376587503,  4.138236370809,  4.015594565586)
        (sa,sb,sc)[2]=(  3.979975802405,  3.582292852693,  4.084506672553)
        (sa,sb,sc)[3]=(  3.858895022036,  4.110642310930,  4.069782913762)
    M(x,y,z)[0]=(  0.117546668879,  1.491492178271,  3.764555292010)
    M(x,y,z)[1]=(  0.249999787814,  0.750000060576,  3.999999981443)
    M(x,y,z)[2]=(  2.003692652636,  0.078506314801,  3.437915051312)
    M(x,y,z)[3]=( -0.503154708657, -0.336031087029,  3.811166388233)
=================================================================

Uclue Researcher Answer clarification by Researcher mathtalk on Mon 25 Jan 2010 - 3:01 pm UTC:

Distinguishing the "correct" M is based on knowledge of the angles at M
subtended by AD,BD,CD (the three angles not used so far).  Ordinarily we
will only need one of those angles to tell which of the candidate locations
is right.

So for now let's just test the angle AMD, or its proxy the cosine:

cos(Angle AMD) = (M-A).(M-D)/(|M-A|*|M-D|)

for simplicity as A is the origin and D is (1,1,0).  Note M-D has the same
length as M-A with M = (0.25,0.75,4.0):

cos(Angle AMD) = (0.25*(0.25-1) + 0.75*(0.75-1) + 4*4)/SQRT(16.625*16.625)

               = 0.939849624

As before the locus of points M which make this angle form a "toroidal"
surface around the axis AD.  If by coincidence more than one candidate
seems to meet the mark, we still have angles BMD and CMD to fall back on.

regards, mt

Comment by eldenc on Mon 25 Jan 2010 - 5:07 pm UTC:

In your example case, what are the angles Angle AMD, Angle BMD, Angle CMD?

Uclue Researcher Answer clarification by Researcher mathtalk on Mon 25 Jan 2010 - 5:39 pm UTC:

I did a quick calculation based on the vector cosine formula:

 angle |    cosine    |    radians
 ------------------------------------
  AMD  |  0.939849624 |  0.348606514
  BMD  |  0.970476876 |  0.243596174
  CMD  |  0.969578653 |  0.247292755

Hope that helps!

Uclue Researcher Answer clarification by Researcher mathtalk on Mon 25 Jan 2010 - 7:39 pm UTC:

Too quick!  I found a mistake in my formulas.

Here are the corrected respective cosines and angles for all four roots as
found by the Web page you linked above.  I suspect it's helpful to see the
effects of the errors introduced:

v = 1.054650618676,  M = (0.276074578,-0.336042042,3.834305562)

 angle |    cosine    |    radians
 -----------------------------------
  AMD  |  0.939384396 |  0.349965926
  BMD  |  0.970385078 |  0.243976478
  CMD  |  0.970301465 |  0.244322374

v = 1.026262454132,  M = (0.261800644,0.07853333,3.970585612)

 angle |    cosine    |    radians
 -----------------------------------
  AMD  |  0.94014532  |  0.347739831
  BMD  |  0.970435765 |  0.243766562
  CMD  |  0.970547765 |  0.243302091

v = 0.984848883367,  M = (0.250000162,0.749978965,4.000002589)

 angle |    cosine    |    radians
 -----------------------------------
  AMD  |  0.939849661 |  0.348606407
  BMD  |  0.970476875 |  0.243596177
  CMD  |  0.969578711 |  0.24729252

v = 0.937635936807,  M = (0.253229519,1.491497084,3.757864854)

 angle |    cosine    |    radians
 -----------------------------------
  AMD  |  0.937225156 |  0.356210179
  BMD  |  0.970463502 |  0.243651616
  CMD  |  0.966062773 |  0.261269744

We should compare these with the "exact" angles:

 angle |    cosine    |    radians
 -----------------------------------
  AMD  |  0.939849624 |  0.348606514
  BMD  |  0.970476876 |  0.243596174
  CMD  |  0.969578653 |  0.247292755

based on:

v = 0.984847609,  M = (0.25,0.75,4.0).  Note that this "real" v differs
from the closest root above by ~10^-6.  As a result the agreement in the
angles AMD,BMD,CMD between the calculated and "real" values is roughly
proportional, while disagreements with "false" roots begins by at least the
fourth decimal place for any of the three angles chosen (angle BMD having
the smallest differences to detect).


regards, mathtalk

Uclue Researcher Answer clarification by Researcher mathtalk on Mon 25 Jan 2010 - 8:10 pm UTC:

Actually I found one more mistake in my formulas, related to what I thought
I fixed last, but it will be a few hours before I have time to recalc.

Basically one of my spreadsheet formulas was linking back to an "exact"
value of u, rather than using the u based on calculated root v.  This would
have affected side length s_B and through it the x-coordinate, probably
reducing the actual variability with different roots.

regards, mt

Comment by eldenc on Mon 25 Jan 2010 - 9:26 pm UTC:

success on the example, points,
Since I know there will be error in the results, I'm choosing the one with
the least err. I calculate the error against all 3 D angles and sum each
absolute error together; then pick the one with the smallest error:
===========================================================
int findBest(double *aMx,double *aMy,double *aMz,int numRes,
         double AMD_radians,double BMD_radians,double CMD_radians){
    int i;
    #define VEC_MINUS(RES,Q,P)
{RES.x=Q.x-P.x;RES.y=Q.y-P.y;RES.z=Q.z-P.z;}
    #define VEC_DOT(Q,P) (Q.x*P.x+Q.y*P.y+Q.z*P.z)
    #define VEC_MAGSQ(Q) (Q.x*Q.x+Q.y*Q.y+Q.z*Q.z)
    //#define VEC_MAG(Q) sqrt(Q.x*Q.x+Q.y*Q.y+Q.z*Q.z)
    struct Point3d {double x,y,z;};
    struct Point3d a={0,0,0};
    struct Point3d b={1,0,0};
    struct Point3d c={0,1,0};
    struct Point3d d={1,1,0};
    double cAMD=cos(AMD_radians);
    double cBMD=cos(BMD_radians);
    double cCMD=cos(CMD_radians);

    double err_min=1.7976931348623158e+308; //max double
    int best_yet=-1;
    for(i=0;i<numRes;i++){
        if(aMx[i] < 0 || aMy[i]<0 || aMz[i] < 0)
            continue;
        struct Point3d m={aMx[i],aMy[i],aMz[i]};
        struct Point3d mLessD; 
        VEC_MINUS(mLessD,m,d);//mLessD
        struct Point3d mLessW;//where W is a,b,c

        VEC_MINUS(mLessW,m,a);
        double error_cAMD = cAMD - VEC_DOT(mLessW,mLessD) / 
                          sqrt(VEC_MAGSQ(mLessW)*VEC_MAGSQ(mLessD));
        VEC_MINUS(mLessW,m,b);
        double error_cBMD = cBMD - VEC_DOT(mLessW,mLessD) /
                         sqrt(VEC_MAGSQ(mLessW)*VEC_MAGSQ(mLessD));
        VEC_MINUS(mLessW,m,c);
        double error_cCMD = cCMD - VEC_DOT(mLessW,mLessD) / 
                         sqrt(VEC_MAGSQ(mLessW)*VEC_MAGSQ(mLessD));

        dprintf1("    M=(%g,%g,%g)\n",aMx[i],aMy[i],aMz[i]);
        dprintf1("        error_cBMD "GG"\n",error_cBMD);
        dprintf1("        error_cAMD "GG"\n",error_cAMD);
        dprintf1("        error_cCMD "GG"\n",error_cCMD);

        double error = fabs(error_cAMD)
                     + fabs(error_cBMD)
                     + fabs(error_cCMD);
        dprintf1("        error sum abs "GG"\n",error);

        if(error < err_min){
            err_min=error;
            best_yet=i;
        }
    }
    return best_yet;
}


=================================================================
    Given the angles about M a_radians=  0.347359178898,b_radians= 
0.247292756478,c_radians=  0.243596173163
    M(x,y,z)[0]=(  0.117546668879,  1.491492178271,  3.764555292010)
    M(x,y,z)[1]=(  0.249999787814,  0.750000060576,  3.999999981443)
    M(x,y,z)[2]=(  2.003692652636,  0.078506314801,  3.437915051312)
    M(x,y,z)[3]=( -0.503154708657, -0.336031087029,  3.811166388233)
    M=(0.117547,1.49149,3.76456)
        error_cBMD  -0.000451615092
        error_cAMD   0.002439361691
        error_cCMD   0.003017927362
        error sum abs   0.005908904145
    M=(0.25,0.75,4)
        error_cBMD  -0.000000000337
        error_cAMD  -0.000000000068
        error_cCMD  -0.000000000056
        error sum abs   0.000000000461
    M=(2.00369,0.0785063,3.43792)
        error_cBMD   0.007713507165
        error_cAMD   0.005092855010
        error_cCMD  -0.002262297516
        error sum abs   0.015068659690
M=(0.25,0.75,4)

PASSED Does calcLocationMFrom6Angles() think the solution is correct
	  actual=1.000000	expected=1.000000	tolerance: +/-0.001000
		  delta = 0.000000
PASSED Mx
	  actual=0.250000	expected=0.250000	tolerance: +/-0.000250
		  delta = -0.000000
PASSED My
	  actual=0.750000	expected=0.750000	tolerance: +/-0.000750
		  delta = 0.000000
PASSED Mz
	  actual=4.000000	expected=4.000000	tolerance: +/-0.004000
		  delta = -0.000000
  summary:
  # of tests complete = 4
  # of tests failed   = 0
  # of tests passes   = 4
OverAll results for test: PASSED -- yeah

Comment by eldenc on Mon 25 Jan 2010 - 9:33 pm UTC:

Hopefully, tonight I'll get a chance to apply the formula against the real
data from the camera.  I think my previous data set may have been corrupted
by an IR reflective ruler.
========================================================
#define DISTANCE(ax,ay,bx,by) sqrt((ax-bx)*(ax-bx)+(ay-by)*(ay-by))

int calcLocationM(double ax,double ay,
                  double bx,double by,
                  double cx,double cy,
                  double dx,double dy,
                  double *Mx,double *My,double *Mz){
    dprintf1("For points:\n"
             "  A=(%5.1f,%5.1f)\n"
             "  B=(%5.1f,%5.1f)\n"
             "  C=(%5.1f,%5.1f)\n"
             "  D=(%5.1f,%5.1f)\n",ax,ay,bx,by,cx,cy,dx,dy);
    //this is specific to the Wii Mote Camera
    double radians_per_pixel=0.00143066; //atan(12.5 cm /54.0 cm)/159
pixels
    //angles -- eg BMC_radians=the angle subtended by bc from 3d point M
    //the first 3 are for determining the candiate positions
    double AMB_radians=DISTANCE(ax,ay,bx,by)*radians_per_pixel;
    double AMC_radians=DISTANCE(ax,ay,cx,cy)*radians_per_pixel;
    double BMC_radians=DISTANCE(bx,by,cx,cy)*radians_per_pixel;
    //the second 3 are for isolating to 1 solution
    double AMD_radians=DISTANCE(ax,ay,dx,dy)*radians_per_pixel;
    double BMD_radians=DISTANCE(bx,by,dx,dy)*radians_per_pixel;
    double CMD_radians=DISTANCE(cx,cy,dx,dy)*radians_per_pixel;

    int success=calcLocationMFrom6Angles(
                  BMC_radians,AMC_radians,AMB_radians,
                  AMD_radians,BMD_radians,CMD_radians,
                  Mx,My,Mz);
    dprintf1("success=%d M=(%g,%g,%g)\n\n",success,*Mx,*My,*Mz);
    return success;
}

Uclue Researcher Answer clarification by Researcher mathtalk on Tue 26 Jan 2010 - 12:38 pm UTC:

Below are the angles involving D for numerically computed roots v, redone
because of the error mentioned above (using "exact" u with computed v). 
This error did not affect the "exact" angles for the true M, so see the
earlier post for those.

v = 1.054650618676,  M = (-0.503133775,-0.336042042,3.811164221)

 angle |    cosine    |    radians
 ------+--------------+-------------
  AMD  |  0.945961212 |  0.330250282
  BMD  |  0.972886341 |  0.23339699
  CMD  |  0.973124346 |  0.232365694

v = 1.026262454132,  M = (2.003142516,0.07853333,3.438242245)

 angle |    cosine    |    radians
 ------+--------------+-------------
  AMD  |  0.934756768 |  0.363222484
  BMD  |  0.962766421 |  0.273740597
  CMD  |  0.971838272 |  0.237886149

v = 0.984848883367,  M = (0.250007551,0.749978965,4.000002127)

 angle |    cosine    |    radians
 ------+--------------+-------------
  AMD  |  0.939849634 |  0.348606485
  BMD  |  0.970476849 |  0.243596283
  CMD  |  0.969578691 |  0.247292603

v = 0.937635936807,  M = (0.117546398,1.491497084,3.764552602)

 angle |    cosine    |    radians
 ------+--------------+-------------
  AMD  |  0.937410232 |  0.355679076
  BMD  |  0.970928492 |  0.241716648
  CMD  |  0.966560692 |  0.259335119

Distinguishing the approximations to M is now a good bit easier than the
earlier results suggested.  The best has angles that deviate from the exact
angles by only 1.5E-7 or so, while discrepancies for other roots are over
1.0E-3 with regard to any of the three angles involving D.

It's also an opportune time to collect our corrections to formulas for the
coefficients of the quartic:







regards, mathtalk

Comment by eldenc on Sat 30 Jan 2010 - 9:11 am UTC:

While I haven't figured out the correct multiplier for the pixels to
radians conversion (its close), over all it seems to work well.  Thanks!

You can playback some of my wiimote recordings via
wget
http://eldenc.tripod.com/resection4knowPointsAndAngles.20100129B.tar.gz
read the top of msg_special.py for how to install gnu_plot python
Then run it via 
python msg_special.py upAndDownAtXeqYeq5.txt

Or if you have a wiimote handy you can install wmgui (sudo apt-get install
wmgui, if your in ubuntu), lswm and record your own via
python msg_special.py 00:27:09:33:BB:01
(get the number from lswm).

Two more questions, in testing it appears that this works beyond the first
quadrant do you have an off the cuff answer for how far?
Also at what angle from the origin is formula the most accurate?

And for my curiosity,
How crazy is the math for arbitrary know points?

Thanks for your time and effort, and WOW that's kinda cool!

4 stars Accepted and rated by eldenc on Sat 30 Jan 2010 - 9:17 am UTC:

While the answer was much more complicated that I thought it would be,
mathtalk figured it out and went the extra mile to help me verify his
solution and my code.  Thanks!

Uclue Researcher Answer clarification by Researcher mathtalk on Mon 1 Feb 2010 - 3:47 pm UTC:

We do have a couple of Wii controllers, though my wife, daughter, and her
friends would probably rather I got a spare one to experiment with!

I think the general case will not be too bad to write.  I was fearful of
trying to "debug" it in my initial answer, but now that we've tested the
isoceles right triangle case pretty thoroughly, I think we can leverage
those answers to validate the general case.

As to the accuracy of the method, there are two things to keep in mind.  As
the angle of the camera's line of sight to the plane in which the triangle
lies becomes increasingly acute, we lose information due to foreshortening
of one or more legs of the triangle.  [We also lose information at a longer
distance from the target, but in my optimistic thinking this is less
serious because (depending on how fast the plane flies) longer distance
means more time left to adjust the flight path.]  I think I can quantify
this in terms of how "sensitive" (size of derivatives) the observed angles
are to changing the camera location.  I did scratch this out somewhat in my
legal pad, so let me clean it up a bit and I'll post the analysis.

The other accuracy issue has to do with the numerical methods involved.  As
mentioned before, Grunert's approach introduces a "singularity" through the
rational expression for u in terms of v, so that for v near this
singularity the computation of u is unreliable as presented.  Some of the
other methods that have been proposed/studied avoid this, cf. the paper by
Haralick et al cited in my original answer, but are more complicated to
implement.  Since the plane is in motion, my (again possibly
overoptimistic) thinking was that the passage near the singular value for v
(an artifact of computation and not a physical effect) would be brief
enough not to matter.  [In our worked example the singular value for v lies
closest to the second root of the quartic for v, and the third root is the
"correct" one as detected by using the fourth point.]

I also have a bunch of references gathered at the earliest stage of working
on this interesting question, set aside until we got the crux of the
problem solved since they bear on such ancillary issues as the calibration
of the camera angles.  Since you're now "focused" on that, I hope it will
be useful to have them.

regards, mathtalk

Comment by eldenc on Mon 1 Feb 2010 - 8:50 pm UTC:

Yea, if your using the wii mote that has already been associated with a Wii
that is in range, it will steal it away from your ubuntu 9.10 bluetooth
connection when the wii is powered on (I think they have some 'special'
bluetooth commands).  (My kid's seemed to think it was funny, so they would
do it intentionally!)  So I got two for me :-)....one to pull apart and put
just the camera on the plane, and one for testing this algorithm.
Hopefully, I'll get some flight derived data this week end.  The before
mentioned python/c data is from a box of Christmas lights n a burrito box.

Comment by User myoarin on Tue 2 Feb 2010 - 5:56 pm UTC:

Wow!  Congratulations!  (not that I understood anything beyond that it was
about trying to land a remote controlled model plane)

It just lets me wonder (capital W) how a human with two eyes can stand
somewhere on a tennis court (part of the mental calculation) and see a ball
arching over the net (tilt of head and curve and direction of the ball
calculated) and from the flight of the ball judge whether it will land
behind him on the court or beyond the base line.

Of course, depth perception with two eyes helps  - and a lifetime of
experience -  but still ...

That is not a suggestion that a second camera and trying to integrate the
images would be a better or easier solution.

Comment by eldenc on Wed 3 Feb 2010 - 11:07 pm UTC:

There are a few issues with using multiple camera's, 1) the accuracy of the
viewing angle between the cameras is critical, which is difficult given
that to improve accuracy you want to be as far apart as possible, but, of
course, the farther apart they are...holding them rigidly becomes
exponentially more difficult (especially on a foam A/C!)  2) with closely
spaced cameras, you need higher resolutions to obtain the same accuracy,
and finally 3) [the driver for me], the wii mote cameras are on a
particular I2C address, which would require that I have 2 different i2c
buses, but alas I only have one on my current system, 4)the simpler the
system the more reliable it is.

On tennis court issue, we are not really using our stereoscopic view to
determine distance, we are mostly using our knowledge of the size of the
ball and the pattern of flight that we have seen many times before and for
players better than me, they are guessing the balls flight pattern from
watching the opponent's swing.  We are also using time correlation of the
movement, not simply one image.

Comment by eldenc on Wed 3 Feb 2010 - 11:16 pm UTC:

So do the 'singularities' form a ellipsoid, a ray, or are they discreet
points?  I don't think I've seen any yet. (But maybe I miss-labeled the
singularities as a hardware issues)

Comment by User myoarin on Thu 4 Feb 2010 - 9:39 pm UTC:

Hi Eldenc,

Thanks for your input.  Makes sense.

I hope your plane lands where you want it to.

Myo

Actions: Add Comment

Bookmark it!   Del.icio.us Digg Furl Reddit Yahoo MyWeb StumbleUpon Technorati Mixx MySpace Facebook

Frequently Asked Questions | Terms & Conditions | Disclaimer | Privacy Policy | Contact Us | Spread the word!

© 2010 Uclue Ltd