Calculating the intersection of spheres [Trilateration Calculation]

Hi Everyone,

I have a mathematical calculation I needed solved, to do with the intersection of spheres.

I have a node transmitting a message and it is received by 3 or more gateways (base stations). The location of the node is unknown and I want to calculate it.

The gateway location and the timestamp the message arrives is known.
The location is in the msg.payload.uplink_message.rx_metadata[i].location.latitude and msg. payload.uplink_message.rx_metadata[i].location.longitude

Time stamp is msg. payload.uplink_message.rx_metadata[i].time

Here I am showing an example of 3 gateways, but it could be a lot more, 4 gateways will give 3D accuracy.

The flow below is a inject node with the JSON in it.

[{"id":"333f342c.ef334c","type":"inject","z":"1f9de5c0.4c944a","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"end_device_ids\":{\"device_id\":\"24e124136a512983\",\"application_ids\":{\"application_id\":\"temperature-collection\"},\"dev_eui\":\"24E124136A512983\",\"join_eui\":\"70B3D57ED004305B\",\"dev_addr\":\"260BF170\"},\"correlation_ids\":[\"as:up:01FDP93T732QMWB77C2GWGB5M3\",\"gs:conn:01FCN5FJXHANYS2X1NTMQ9NKZY\",\"gs:up:host:01FCN5FJXWKEYM0CP1DCD3BFBA\",\"gs:uplink:01FDP93T056T1KWPXRAR2C5N7D\",\"ns:uplink:01FDP93T07FYVH0SEK6FD6G6MM\",\"rpc:/ttn.lorawan.v3.GsNs/HandleUplink:01FDP93T07PK65YNJWD0CRAPBF\",\"rpc:/ttn.lorawan.v3.NsAs/HandleUplink:01FDP93T72WEB48CMXWTJCBN0A\"],\"received_at\":\"2021-08-22T06:35:06.852634186Z\",\"uplink_message\":{\"session_key_id\":\"AXtn1vl04Sbzy4kNIDg/Cg==\",\"f_port\":85,\"f_cnt\":663,\"frm_payload\":\"A2eLAARokQ==\",\"decoded_payload\":{\"humidity\":72.5,\"temperature\":13.9},\"rx_metadata\":[{\"gateway_ids\":{\"gateway_id\":\"tech5-alverstone-02-dbn\",\"eui\":\"313330374E005900\"},\"time\":\"2021-08-22T06:35:06.519602Z\",\"timestamp\":506974466,\"rssi\":-104,\"channel_rssi\":-104,\"snr\":6,\"location\":{\"latitude\":-29.770195,\"longitude\":30.716669,\"altitude\":950,\"source\":\"SOURCE_REGISTRY\"},\"uplink_token\":\"CiUKIwoXdGVjaDUtYWx2ZXJzdG9uZS0wMi1kYm4SCDEzMDdOAFkAEIKi3/EBGgwImuCHiQYQpt2srAIg0N+h0OCF/QE=\",\"channel_index\":6},{\"gateway_ids\":{\"gateway_id\":\"tech5-gillits-01-dbn\",\"eui\":\"3133303746002800\"},\"time\":\"2021-08-22T06:35:06.523276Z\",\"timestamp\":388469847,\"rssi\":-115,\"channel_rssi\":-115,\"snr\":-9.25,\"location\":{\"latitude\":-29.796528,\"longitude\":30.790431,\"altitude\":647,\"source\":\"SOURCE_REGISTRY\"},\"uplink_token\":\"CiIKIAoUdGVjaDUtZ2lsbGl0cy0wMS1kYm4SCDEzMDdGACgAENeonrkBGgwImuCHiQYQsYP9rAIg2OftlKffYQ==\",\"channel_index\":6},{\"gateway_ids\":{\"gateway_id\":\"on-the-hill-01\",\"eui\":\"00800000A000104F\"},\"time\":\"2021-08-22T06:35:06.521836Z\",\"timestamp\":2525021188,\"rssi\":-74,\"channel_rssi\":-74,\"snr\":10.5,\"location\":{\"latitude\":-29.806432,\"longitude\":30.771859,\"altitude\":615,\"source\":\"SOURCE_REGISTRY\"},\"uplink_token\":\"ChwKGgoOb24tdGhlLWhpbGwtMDESCACAAACgABBPEISIg7QJGgwImuCHiQYQxtqLuAIgoN/2t76fDg==\",\"channel_index\":6}],\"settings\":{\"data_rate\":{\"lora\":{\"bandwidth\":125000,\"spreading_factor\":7}},\"data_rate_index\":5,\"coding_rate\":\"4/5\",\"frequency\":\"867700000\",\"timestamp\":506974466,\"time\":\"2021-08-22T06:35:06.519602Z\"},\"received_at\":\"2021-08-22T06:35:06.631439294Z\",\"consumed_airtime\":\"0.056576s\",\"locations\":{\"lora-cloud-geolocation-v3-rssi\":{\"latitude\":-29.807015,\"longitude\":30.772747,\"accuracy\":2337,\"source\":\"SOURCE_LORA_RSSI_GEOLOCATION\"}},\"version_ids\":{\"brand_id\":\"milesight-iot\",\"model_id\":\"em300-th\",\"hardware_version\":\"V2.2\",\"firmware_version\":\"1.15\",\"band_id\":\"EU_863_870\"},\"network_ids\":{\"net_id\":\"000013\",\"tenant_id\":\"ttn\",\"cluster_id\":\"ttn-eu1\"}}}","payloadType":"json","x":210,"y":520,"wires":[["7aede05c.a9783"]]},{"id":"7aede05c.a9783","type":"debug","z":"1f9de5c0.4c944a","name":"Decoder 1","active":true,"tosidebar":true,"console":false,"tostatus":true,"complete":"true","targetType":"full","statusVal":"payload","statusType":"auto","x":530,"y":500,"wires":[]}]


Are you asking how to implement a solution for that equation in a function node? If so then I think you need to find a JavaScript (or possibly python) solution elsewhere.

Yes, I know it is more related to JavaScript(Python), but the last time I did mathematics like this is long, long time back.

Need to find a Maths master.

It helps to know the name of the tool your trying to use. This is a trilateration problem. Old school single engine pilots do the opposite of this with old AM radio towers to figure out where we are at. Heck only need 1 tower because as we move towards it we can plot 2 points over time.

Your example only gives one tower. Be helpful to have 3

Ill take a stab at it next weekend if no one else touches it..... I do like my Maths.

Question: does the node move around or is it stationary ? if it moves you only need one tower to pull off a ruff estimate of its location +/- the opposite side of the radius. 2 towers fixes that for a moving node.

Factors that mess up the equation. If the tower(s) is/are on hill(s) at high elevations and the node is low to the ground then your estimation of location err goes up. or you need 3 towers for sure!

The node moves slowly (1-15km/h), but mostly stationery.

Towers - not very specific of location, varies some on hills, buildings, but mostly 10m AGL

Nodes are generally not more than 3m AGL

rx_metadata: array[3]
0: object
gateway_ids: object
gateway_id: "tech5-alverstone-02-dbn"
eui: "313330374E005900"
time: "2021-08-22T06:35:06.519602Z"
timestamp: 506974466
rssi: -104
channel_rssi: -104
snr: 6
location: object
latitude: -29.770195
longitude: 30.716669
altitude: 950
uplink_token: "CiUKIwoXdGVjaDUtYWx2ZXJzdG9uZS0wMi1kYm4SCDEzMDdOAFkAEIKi3/EBGgwImuCHiQYQpt2srAIg0N+h0OCF/QE="
channel_index: 6
1: object
gateway_ids: object
time: "2021-08-22T06:35:06.523276Z"
timestamp: 388469847
rssi: -115
channel_rssi: -115
snr: -9.25
location: object
latitude: -29.796528
longitude: 30.790431
altitude: 647
uplink_token: "CiIKIAoUdGVjaDUtZ2lsbGl0cy0wMS1kYm4SCDEzMDdGACgAENeonrkBGgwImuCHiQYQsYP9rAIg2OftlKffYQ=="
channel_index: 6
2: object
gateway_ids: object
gateway_id: "on-the-hill-01"
eui: "00800000A000104F"
time: "2021-08-22T06:35:06.521836Z"
timestamp: 2525021188
rssi: -74
channel_rssi: -74
snr: 10.5
location: object
latitude: -29.806432
longitude: 30.771859
altitude: 615
uplink_token: "ChwKGgoOb24tdGhlLWhpbGwtMDESCACAAACgABBPEISIg7QJGgwImuCHiQYQxtqLuAIgoN/2t76fDg=="
channel_index: 6

I just could not stop thinking about this locator :slight_smile:

So I played around with some math in javascript ( getting roots too dang slow ) and forget a differential.

Then did some hunting on NPM figuring someone with way more skill than me probly did a 100X better job of it.

Ohhhhh Looks like I might be making a new node-red-contrib

First we need to sort out the lat / lon / height issues ---> geodetic-to-ecef - npm
Now we can use ---> lm-trilateration3d - npm

On last issue I'm sorting out is distance now. speed of (EM waves in a vacuum)

Been reading a bit.

As we are dealing with a RF link, we do have RSSI as well to help getting the estimation correct. BUT, the RF could be attenuated adversely between the node and tower as it have to travel thru a brick wall, but could be used as a reference to guess if our calculation is relatively accurate. There are also some reference to RSSI on this page.

I am using currently a call to a API, but some how the error gets worse when they have more than 3 points and they don't exclude 2 point calculations.

This is a stationery node over the last 24 hours.


299 792 458 m / s

Last time I looked, the earth had an atmosphere:-)


We are slowly sucking it up, so we are going to end up with a vacuum. :grinning:

This topic was automatically closed 60 days after the last reply. New replies are no longer allowed.