Sound Location Part 2 with the Qwiic Sound Trigger and the u-blox ZED-F9x

Pages
Contributors: PaulZC
Favorited Favorite 3

Here There Be Dragons!

Sound_Trigger_Analyzer_2D.py can work with any configuration of the trigger positions (so long as the X coordinate of C is between A and B). They do not need to be arranged in a nice right-angled triangle with A-C pointing North. Don’t believe me? Want proof? Good for you! OK. Brace yourself. Here we go… Here is the actual math used in Sound_Trigger_Analyzer_2D.py.

Sensor Coordinates

Let’s suppose our three sound triggers are arranged such that they form a triangle ABC:

Pictured is the triangle formed from points A B C

We know the length of the sides: AB, AC and BC.

We know the coordinates of A and B. A is our origin and is located at (0,0). B is due ‘East’ of A and defines our X axis. So we say that B is located at (AB,0). But we don’t yet know the location of C. We need to calculate it. Let’s call the location of C (CX,CY).

If we draw a line from C so it meets line A-B at right angles:

Pictured is the triangle divided into two smaller right triangles

Pythagoras’ Theorem tells us that:

  • Equation 1: AC2 = CX2 + CY2
  • Equation 2: BC2 = ( AB - CX )2 + CY2

If we rearrange those equations, bringing CY2 to the left and multiplying out the brackets, we get:

  • CY2 = AC2 - CX2
  • CY2 = BC2 - AB2 + 2.AB.CX - CX2

Because those two equations are equal, we can arrange them as:

  • AC2 - CX2 = BC2 - AB2 + 2.AB.CX - CX2

The two -CX2 cancel out. Rearranging, we get:

  • CX = ( AC2 - BC2 + AB2 ) / 2.AB

We can find CY by inserting the value for CX into one of our earlier equations:

  • CY2 = AC2 - CX2

So:

  • CY = √ ( AC2 - CX2 )

We now have the coordinates for C: ( CX , CY )

Sound Event Timings

Now, let’s suppose our sound trigger system is running and it detects a sound. Let’s call the location of the sound S and give it coordinates ( SX , SY ):

Pictured are the coordinates of point S and the triangles formed from it

Our three systems are logging the time the sound arrives at each sensor (very accurately!).

The time taken for the sound to reach A is: the distance from S to A divided by the speed of sound. Likewise for B and C.

If all three systems hear the sound at the exact same time, then we know that the sound took an equal time to travel from S to A, B and C. That’s a special case where the distances SA, SB and SC are equal (equidistant). But usually sensors B and C will hear the sound at different times to A due to the distances SB and SC being different to SA. We need to include those differences in distance in our calculation. To save some typing, let’s call the distance SA: D

  • SB = D + DdiffB
  • SC = D + DdiffC

DdiffB is the difference between SB and D. Likewise, DdiffC is the difference between SC and D. Note that DdiffB or DdiffC could be negative if the source of the sound is closer to B or C than A.

Sensors B and C will hear the sound earlier or later than A depending on DdiffB and DdiffC.

What we do not know is how long the sound took to travel from S to A, because we do not know the distance D. That’s what we need to calculate,

What we do know is the difference in the time of arrival of the sound at our three sensors. If we bring the three sets of sensor data together, we can calculate the difference in the time of arrival at each sensor. Let’s say that:

  • The time recorded by trigger A is timeA
  • The time recorded by trigger B is timeB
  • The time recorded by trigger C is timeC

Let’s calculate the differences in those times:

  • TdiffB = timeB - timeA
  • TdiffC = timeC - timeA

Again, TdiffB and TdiffC could be negative if the source of the sound is closer to B or C than A.

Sound Event Coordinates

We can convert those differences in time into differences in distance by multiplying by the speed of sound:

  • DdiffB = TdiffB * speed_of_sound
  • DdiffC = TdiffC * speed_of_sound

Now we can use Pythogoras’ Theorem as before to study our triangles:

  • D2 = SX2 + SY2
  • (D + DdiffB)2 = (AB - SX)2 + SY2

We need to add an extra triangle to include SC:

Pictured are additional right triangles formed around point S

The width of the new triangle is:

  • CX - SX

The height of the new triangle is:

  • CY - SY

So, using Pythagoras’ Theorem again:

  • (D + DdiffC)2 = (CX - SX)2 + (CY - SY)2

We now have our three equations:

  • Equation 3: D2 = SX2 + SY2
  • Equation 4: (D + DdiffB)2 = (AB - SX)2 + SY2
  • Equation 5: (D + DdiffC)2 = (CX - SX)2 + (CY - SY)2

We need to solve for D. To begin, let’s substitute the value for SY2 from the second equation into the first equation, so we can find the relationship between D and SX:

  • D2 = SX2 + (D + DdiffB)2 - (AB - SX)2

Multiplying out the brackets, that becomes:

  • D2 = SX2 + D2 + 2.DdiffB.D + DdiffB2 - AB2 + 2.AB.SX - SX2

As before, the D2 cancel and so do the SX2 leaving:

  • 0 = 2.DdiffB.D + DdiffB2 - AB2 + 2.AB.SX

Rearranging:

  • 2.AB.SX = AB2 - 2.DdiffB.D - DdiffB2

Divide through by 2.AB:

  • SX = ( AB2 - 2.DdiffB.D - DdiffB2 ) / 2.AB

Let’s make life easier for ourselves and say that:

  • Equation 6: SX = SXa.D + SXb

Where:

  • SXa = ( -2.DdiffB ) / 2.AB
  • SXb = ( AB2 - DdiffB2 ) / 2.AB

We can calculate both values because we know AB and can calculate DdiffB:

  • DdiffB = TdiffB * speed_of_sound = ( timeB - timeA ) * speed_of_sound

Looking at equation 3 again:

  • D2 = SX2 + SY2

If we replace SX with ( SXa.D + SXb ), we get:

  • D2 = ( SXa.D + SXb )2 + SY2

Rearranging:

  • SY2 = D2 - ( SXa.D + SXb )2

Multiplying out the bracket, it becomes:

  • SY2 = D2 - SXa2.D2 - 2.SXa.SXb.D - SXb2

Simplifying:

  • SY2 = ( 1 - SXa2 ).D2 - 2.SXa.SXb.D - SXb2

So:

  • Equation 7: SY = √ ( ( 1 - SXa2 ).D2 - 2.SXa.SXb.D - SXb2 )

That’s ever so slightly horrible, but let’s go with it…

Now we have values for SX and SY in terms of D, which we can plug into equation 5:

  • (D + DdiffC)2 = (CX - SX)2 + (CY - SY)2

Substituting for SX and SY we get:

  • (D + DdiffC)2 = (CX - ( SXa.D + SXb ) )2 + (CY - √ ( ( 1 - SXa2 ).D2 - 2.SXa.SXb.D - SXb2 ) )2

Multiplying out the brackets gives (brace yourself!):

  • D2 + 2.DdiffC.D + DdiffC2 = CX2 - 2.CX.SXa.D - 2.CX.SXb + SXa2.D2 + 2.SXa.SXb.D + SXb2 + CY2 - 2.CY.√ ( ( 1 - SXa2 ).D2 - 2.SXa.SXb.D - SXb2 ) + ( 1 - SXa2 ).D2 - 2.SXa.SXb.D - SXb2

Simplifying and moving everything but the root to the left gives:

  • ( 1 - SXa2 - ( 1 - SXa2 )).D2 + ( 2.DdiffC + 2.CX.SXa - 2.SXa.SXb + 2.SXa.SXb).D + DdiffC2 - CX2 + 2.CX.SXb - SXb2 - CY2 + SXb2 = -2.CY.√ ( ( 1 - SXa2 ).D2 - 2.SXa.SXb.D - SXb2 )

Fortunately the D2 term cancels out completely, which is good news. If it didn’t, we’d have a quartic equation to solve instead of a quadratic…

Simplifying:

  • ( 2.DdiffC + 2.CX.SXa).D + DdiffC2 - CX2 + 2.CX.SXb - CY2 = -2.CY.√ ( ( 1 - SXa2 ).D2 - 2.SXa.SXb.D - SXb2 )

Dividing through by -2.CY gives:

  • ( ( 2.DdiffC + 2.CX.SXa ).D + DdiffC2 - CX2 + 2.CX.SXb - CY2 ) / -2.CY = √ ( ( 1 - SXa2 ).D2 - 2.SXa.SXb.D - SXb2 )

We now need to square both sides to get rid of the root. Painful… But we need to do it… But first, to make life easier for ourselves, let’s simplify further and say:

  • da.D + db = √ ( ( 1 - SXa2 ).D2 - 2.SXa.SXb.D - SXb2 )

Where:

  • da = ( 2.DdiffC + 2.CX.SXa ) / -2.CY
  • db = ( DdiffC2 - CX2 + 2.CX.SXb - CY2 ) / -2.CY

Remember that we can already calculate values for da and db because we know or can calculate values for: DdiffC; CX; SXb; and CY.

Square both sides:

  • da2.D2 + 2.da.db.D + db2 = ( 1 - SXa2 ).D2 - 2.SXa.SXb.D - SXb2

Moving the terms on the right over to the left:

  • ( da2 - ( 1 - SXa2 ) ).D2 + ( 2.da.db + 2.SXa.SXb ).D + db2 + SXb2 = 0

That’s a quadratic equation which we can solve in the usual way. Let’s make:

  • qa = da2 - 1 + SXa2
  • qb = 2.da.db + 2.SXa.SXb
  • qc = db2 + SXb2

Remember that we can already calculate values for qa, qb and qc because we already know: da; SXa; db; and SXb.

Solving the quadratic::

  • D = ( -qb +/- √( qb2 - 4.qa.qc ) ) / 2.qa

That gives us two possible values for D. One will be negative or otherwise invalid, leaving us with a value for D.

We can then plug the value for D into equation 6 to find the X coordinate of S because we already know the values of SXa and SXb:

  • SX = SXa.D + SXb

We can then calculate the Y coordinate of S using equation 3:

  • D2 = SX2 + SY2
  • SY = √( D2 - SX2 )

Enjoy your coordinates!