How are your distances determined?
float ra = beacon1.filteredDistance;
float rb = beacon2.filteredDistance;
float rc = beacon3.filteredDistance;
I have also The Trialateration code for 3 Beacons
Sub Trilaterate(positions() As Float, distances() As Float) As Float()
If positions.Length <> 6 Then Log("!!! s/b 3 positions")
Dim xa As Float = positions(0)
Dim ya As Float = positions(1)
Dim xb As Float = positions(2)
Dim yb As Float = positions(3)
Dim xc As Float = positions(4)
Dim yc As Float = positions(5)
If distances.Length <> 3 Then Log("!!! s/b 3 distances")
Dim ra As Float = distances(0)
Dim rb As Float = distances(1)
Dim rc As Float = distances(2)
'var S = (Math.pow(xc, 2.) - Math.pow(xb, 2.) + Math.pow(yc, 2.) - Math.pow(yb, 2.) + Math.pow(rb, 2.) - Math.pow(rc, 2.)) / 2.0;
Dim S As Float = (xc * xc - xb * xb + yc * yc - yb * yb + rb * rb - rc * rc) / 2
'var T = (Math.pow(xa, 2.) - Math.pow(xb, 2.) + Math.pow(ya, 2.) - Math.pow(yb, 2.) + Math.pow(rb, 2.) - Math.pow(ra, 2.)) / 2.0;
Dim T As Float = (xa * xa - xb * xb + ya * ya - yb * yb + rb * rb - ra * ra) / 2
'var y = ((T * (xb - xc)) - (S * (xb - xa))) / (((ya - yb) * (xb - xc)) - ((yc - yb) * (xb - xa)));
Dim y As Float = ((T * (xb - xc)) - (S * (xb - xa))) / (((ya - yb) * (xb - xc)) - ((yc - yb) * (xb - xa)))
'var x = ((y * (ya - yb)) - T) / (xb - xa);
Dim x As Float = ((y * (ya - yb)) - T) / (xb - xa)
Return Array As Float(x, y)
End Sub
Dim Positions(6) As Float = Array As Float(0, 0, 100, 0, 0, 100)
Dim NumBeacons As Int = Positions.Length / 2
If Positions.Length <> NumBeacons * 2 Then Log("!!! odd number of beacons")
Log("Random X,Y" & TAB & "Distances A, B, C" & TAB & TAB & "Reconstructed X,Y")
For Burl = 1 To 10
Dim X As Float = Rnd(10, 90)
Dim Y As Float = Rnd(10, 90)
Dim Distances(NumBeacons) As Float
For b = 0 To NumBeacons - 1
Dim dx As Float = X - Positions(b * 2)
Dim dy As Float = Y - Positions(b * 2 + 1)
Distances(b) = Sqrt(dx * dx + dy * dy)
Next
Dim EstLoc(Positions) As Float = Trilaterate(Positions, Distances)
Log( _
X & TAB & _
Y & TAB & _
NumberFormat2(Distances(0), 1, 3, 3, False) & TAB & _
NumberFormat2(Distances(1), 1, 3, 3, False) & TAB & _
NumberFormat2(Distances(2), 1, 3, 3, False) & TAB & _
NumberFormat2(EstLoc(0), 1, 4, 4, False) & TAB & _
NumberFormat2(EstLoc(1), 1, 4, 4, False) _
)
Next
Random X,Y Distances A, B, C Reconstructed X,Y
82 47 94.515 50.329 97.637 82.0000 47.0000
88 45 98.838 46.573 103.774 88.0000 45.0000
64 47 79.404 59.203 83.096 64.0000 47.0000
18 86 87.864 118.828 22.804 18.0000 86.0000
40 82 91.236 101.607 43.863 40.0000 82.0000
47 45 65.069 69.527 72.346 47.0000 45.0000
13 46 47.802 98.412 55.543 13.0000 46.0000
25 55 60.415 93.005 51.478 25.0000 55.0000
46 77 89.694 94.048 51.430 46.0000 77.0000
32 50 59.363 84.404 59.363 32.0000 50.0000
While you look at how good the RSSI distance estimates are, I figured I'd check out that trilateration calculation.
If you transcribe it to B4X eg:
B4X:Sub Trilaterate(positions() As Float, distances() As Float) As Float() If positions.Length <> 6 Then Log("!!! s/b 3 positions") Dim xa As Float = positions(0) Dim ya As Float = positions(1) Dim xb As Float = positions(2) Dim yb As Float = positions(3) Dim xc As Float = positions(4) Dim yc As Float = positions(5) If distances.Length <> 3 Then Log("!!! s/b 3 distances") Dim ra As Float = distances(0) Dim rb As Float = distances(1) Dim rc As Float = distances(2) 'var S = (Math.pow(xc, 2.) - Math.pow(xb, 2.) + Math.pow(yc, 2.) - Math.pow(yb, 2.) + Math.pow(rb, 2.) - Math.pow(rc, 2.)) / 2.0; Dim S As Float = (xc * xc - xb * xb + yc * yc - yb * yb + rb * rb - rc * rc) / 2 'var T = (Math.pow(xa, 2.) - Math.pow(xb, 2.) + Math.pow(ya, 2.) - Math.pow(yb, 2.) + Math.pow(rb, 2.) - Math.pow(ra, 2.)) / 2.0; Dim T As Float = (xa * xa - xb * xb + ya * ya - yb * yb + rb * rb - ra * ra) / 2 'var y = ((T * (xb - xc)) - (S * (xb - xa))) / (((ya - yb) * (xb - xc)) - ((yc - yb) * (xb - xa))); Dim y As Float = ((T * (xb - xc)) - (S * (xb - xa))) / (((ya - yb) * (xb - xc)) - ((yc - yb) * (xb - xa))) 'var x = ((y * (ya - yb)) - T) / (xb - xa); Dim x As Float = ((y * (ya - yb)) - T) / (xb - xa) Return Array As Float(x, y) End Sub
and test it with random points eg:
B4X:Dim Positions(6) As Float = Array As Float(0, 0, 100, 0, 0, 100) Dim NumBeacons As Int = Positions.Length / 2 If Positions.Length <> NumBeacons * 2 Then Log("!!! odd number of beacons") Log("Random X,Y" & TAB & "Distances A, B, C" & TAB & TAB & "Reconstructed X,Y") For Burl = 1 To 10 Dim X As Float = Rnd(10, 90) Dim Y As Float = Rnd(10, 90) Dim Distances(NumBeacons) As Float For b = 0 To NumBeacons - 1 Dim dx As Float = X - Positions(b * 2) Dim dy As Float = Y - Positions(b * 2 + 1) Distances(b) = Sqrt(dx * dx + dy * dy) Next Dim EstLoc(Positions) As Float = Trilaterate(Positions, Distances) Log( _ X & TAB & _ Y & TAB & _ NumberFormat2(Distances(0), 1, 3, 3, False) & TAB & _ NumberFormat2(Distances(1), 1, 3, 3, False) & TAB & _ NumberFormat2(Distances(2), 1, 3, 3, False) & TAB & _ NumberFormat2(EstLoc(0), 1, 4, 4, False) & TAB & _ NumberFormat2(EstLoc(1), 1, 4, 4, False) _ ) Next
then it looks like yourmagicmagnificentmathematical incantations do indeed work:
Log output:Random X,Y Distances A, B, C Reconstructed X,Y 82 47 94.515 50.329 97.637 82.0000 47.0000 88 45 98.838 46.573 103.774 88.0000 45.0000 64 47 79.404 59.203 83.096 64.0000 47.0000 18 86 87.864 118.828 22.804 18.0000 86.0000 40 82 91.236 101.607 43.863 40.0000 82.0000 47 45 65.069 69.527 72.346 47.0000 45.0000 13 46 47.802 98.412 55.543 13.0000 46.0000 25 55 60.415 93.005 51.478 25.0000 55.0000 46 77 89.694 94.048 51.430 46.0000 77.0000 32 50 59.363 84.404 59.363 32.0000 50.0000
I can't see anything there about:DIY localization using radio frequency beacons | Work-is-Playing
but the robot mower project caught my eye, because we moved house a few months ago and the grass here grows like crazy (1cm per day).how good do those distance measurements look in actual real-life use?
I am novice to problem , reading documents online the accuracy may be around 1-4 meters but i obtain bad value mostly when i go far from device. Some more stable value using this filter:I can't see anything there about:
but the robot mower project caught my eye, because we moved house a few months ago and the grass here grows like crazy (1cm per day).
Sub KalmanFilter(distance As Double) As Double
' Initialize variables
Dim q As Double = 0.001 ' Process noise
Dim r As Double = 0.1 ' Measurement noise
Dim x As Double = 0 ' Initial estimate
Dim p As Double = 1 ' Initial error estimate
Dim k As Double ' Kalman gain
' Prediction
x = x ' No prediction step in this example
p = p + q
' Update
k = p / (p + r)
x = x + k * (distance - x)
p = (1 - k) * p
Return x
End Sub
reading documents online the accuracy may be around 1-4 meters but i obtain bad value
Yeah, I was super-impressed by this result, which is ten-times better than anything I ever got when using BLE iTags as beacons:
View attachment 150137
(from DIY localization using radio frequency beacons | Work-is-Playing )
Here is a complete example of how to use the routine to calculate the accurate distance to an iBeacon:
```basic4android
' RSSI smoothing
The value of Alpha in the RSSISmooth() function determines the amount of weight given to the current RSSI value compared to the previous RSSI value. A higher Alpha value will give more weight to the current RSSI value, while a lower Alpha value will give more weight to the previous RSSI value.
In general, an Alpha value between 0.5 and 0.8 is a good starting point. An Alpha value less than 0.5 can cause a response that is too slow to the variation of the RSSI, while an Alpha value greater than 0.8 can cause a response that is too sensitive to the variation of the RSSI.
To choose the optimal value of Alpha, you need to run some tests with your data. You can start with an Alpha value of 0.5 and then increase or decrease it based on your test results.
Here are some tips for choosing the value of Alpha:
If the RSSI is relatively stable, a higher Alpha value can be used.
If the RSSI varies rapidly, a lower Alpha value can be used.
If the RSSI is subject to interference, a lower Alpha value can be used.
Sub RSSISmooth(RSSI, Alpha)
If RSSI < 0 Then
' RSSI invalid
RSSISmooth = RSSI
Else
RSSISmooth = (Alpha * RSSI) + ((1 - Alpha) * RSSISmooth)
End If
Return RSSISmooth
End Sub
' Particle filter
RSSIThreshold is a variable that is used in the routine to calculate the accurate distance to an iBeacon. This variable determines the minimum RSSI value that will be considered valid for distance calculation.
In general, an RSSIThreshold value between -60 and -80 is a good starting point. An RSSIThreshold value less than -60 may cause some iBeacons to be missed, while an RSSIThreshold value greater than -80 may cause inaccurate distance estimates.
To choose the optimal RSSIThreshold value, you need to run some tests with your data. You can start with an RSSIThreshold value of -60 and then increase or decrease it based on your test results.
Here are some tips for choosing the value of RSSIThreshold:
If the environment in which you are measuring distance is noisy, you can use a higher RSSIThreshold value.
If the iBeacon is placed in a location where it is subject to interference, a higher RSSIThreshold value can be used.
If you need greater accuracy in distance estimation, you can use a lower RSSIThreshold value.
Sub ParticleFilter(RSSI, RssiThreshold, ParticleCount, Alpha)
' Create a particle vector
Dim Particles(ParticleCount) As Particle
' Initialize the particles
For i As Integer = 0 To ParticleCount - 1
Particles(i).RSSI = RSSI
Particles(i).Distance = GetDistance(Particles(i).RSSI)
EndFor
' Perform particle update
For i As Integer = 0 To ParticleCount - 1
Particles(i).RSSI = RSSISmooth(Particles(i).RSSI, Alpha)
Particles(i).Distance = GetDistance(Particles(i).RSSI)
EndFor
' Returns the average distance of the particles
Dim DistanceMean As Double
DistanceMean = 0
For i As Integer = 0 To ParticleCount - 1
DistanceMean = DistanceMean + Particles(i).Distance
Next
DistanceMean = DistanceMean / ParticleCount
Return DistanceMean
End Sub
' Main function
Sub Main()
' Settings
Dim RssiThreshold As Double = -50
Dim ParticleCount As Integer = 100
Dim Alpha As Double = 0.7
' Read the RSSI value of the iBeacon
Dim RSSI As Double
RSSI = InputBox("Enter the RSSI value of the iBeacon: ")
' Calculate the accurate distance
Dim Distance As Double
Distance = ParticleFilter(RSSI, RssiThreshold, ParticleCount, Alpha)
' Display the distance
MsgBox(Distance)
End Sub
```
This example works like this:
1. The `RSSISmooth()` function is used to apply an RSSI filter to the RSSI value provided by the user.
2. The `ParticleFilter()` function is used to apply a particle filter to the filtered RSSI value.
3. The `GetDistance()` function is used to calculate the distance of the iBeacon in meters based on its RSSI.
To run this example, you need to set the values of the `RssiThreshold`, `ParticleCount`, and `Alpha` variables according to your needs.
Here's an example of how to use the example:
```
Enter the RSSI value of the iBeacon: -60
Distance: 2.4 meters
```
In this example, the iBeacon distance is 2.4 meters. This is more accurate than the distance calculated without applying RSSI smoothing and particle filtering.
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?