17. Ranging and synchronization
org.arl.unet.Services.RANGING
It is common to use underwater acoustic modems for range estimation, as the travel time of acoustic signals can easily be measured. In
Section 2.3
, we saw that we can use the
range
command to estimate range between nodes. This command uses the RANGING service described below.
Ranging is closely related to time synchronization, since travel time measurement between two nodes requires some sort of synchronization between the nodes. If the nodes are synchronized, one-way travel time (OWTT) can be directly measured and used to estimate range. If the nodes are not synchronized, two-way travel time (TWTT) can be used to measure range and synchronize the nodes simultaneously. The RANGING service supports both modes of ranging, and manages synchronization information between nodes.
The RANGING service also supports ranging to commercial-off-the-shelf (COTS) transponders.
17.1. Overview
The RANGING service provides messages and parameters to support OWTT and TWTT ranging to other Unet nodes or COTS transponders, and to manage synchronization information between the nodes.
17.1.1. Messages
The following messages are defined by the RANGING service:
-
RangeReq
⇒AGREE
/REFUSE
/FAILURE
— measure range to peer node via OWTT or TWTT -
BeaconReq
⇒AGREE
/REFUSE
/FAILURE
— transmit beacon message for OWTT -
RangeNtf
— sent when a range to another node is measured, typically in response toRangeReq
on current node (sent to requester), orBeaconReq
on peer node (sent to agent’s topic) -
InterrogationNtf
— sent on agent’s topic when a ranging interrogration frame is recevied from peer, before a response is sent back -
RespondReq
⇒AGREE
/REFUSE
— if automatic response is disabled, request to respond to interrogation frame (with optional payload)
The use of these messages will become clearer through examples below.
17.1.2. Parameters
The RANGING service does not define any parameters, but the default RANGING agent provides several useful parameters to control its behavior, and to provide status information.
17.2. Ranging agent
17.2.1. Parameters
A few parameters control the behavior of the default ranging agent:
In addition, the following parameters provide defaults for ranging:
-
channel
— channel (DATA/CONTROL) to use for ranging -
maxRange
— maximum expected range to peer (m) -
ipreamble
— interrogation preamble to transmit -
rpreamble
— response preamble to expect after interrogation -
rsignal
— response baseband signal to expect after interrogation -
rdelay
— response delay (seconds) -
threshold
— threshold (0-1) for signal detection, when response is specified as an arbitrary acoustic signal
17.2.2. Indexed parameters
Some parameters can be additionally specified (or overridden) on a per-link basis, using indexed parameters (indexed by the node address of the peer node on the link):
-
address
— peer node address -
channel
— channel (DATA/CONTROL) to use for ranging -
maxRange
— maximum expected range to peer (m) -
ipreamble
— interrogation preamble to transmit -
isignal
— interrogation baseband signal to transmit -
rpreamble
— response preamble to expect after interrogation -
rsignal
— response baseband signal to expect after interrogation -
rdelay
— response delay (seconds) -
data
— payload data to automatically include in response frame -
threshold
— threshold (0-1) for signal detection, when response is specified as an arbitrary acoustic signal -
lifetime
— synchronization validity lifetime (seconds)
The lifetime of syncrhonization information should be set based on the expected drift of modem clocks. Lifetime is defined as the time for the expected clock drift (scaled by speed of sound in water) to exceed the required range estimation accuracy. If a network uses modems with low-drift clocks (such as oven-controlled oscillators), the lifetime can be quite long (hours to days). Without low-drift clocks, reasonable lifetimes may only be in the order of several minutes to tens of minutes.
A few more read-only per-link parameters provide synchronization information about the link, when available:
17.3. Examples
In order to understand how the RANGING service provides OWTT and TWTT ranging, it is instructive to try a few examples using the Netiquette 3-node network simulation (
bin/unet samples/netq-network.groovy
). Start the simulation, and connect to node A:
> agentsForService(org.arl.unet.Services.RANGING) (1)
[ranging]
> ranging
« Range estimator »
Provides time synchronization and range estimation services.
[org.arl.unet.localization.RangingParam]
channel = 2 (2)
ipreamble = 0
mac = mac
maxRange = 3000.0
phy = phy
rdelay = 1.95
respond = true
rpreamble = 0
rsignal = []
threshold = 0.3
> range host('B') (3)
371.09
> ranging << new RangeReq(to: host('B')) (4)
AGREE
ranging >> RangeNtf:INFORM[from:232 to:31 range:371.08856 offset:-1523892589 rxTime:1860655032]
> ntf.range
371.09
1 |
We see that the
ranging
agent provides the RANGING service on the node.
|
2 | The DATA channel (channel 2) is being used for ranging. |
3 |
The
range
command provides us the range to node B of about 371 m.
|
4 |
The
range
command is implemented by sending a
RangeReq
to the
ranging
agent. We directly send that message. As expected, it leads to a
RangeNtf
message that gives us the same range estimate as the
range
command. The
RangeNtf
also provides us time synchronization information between the nodes (as time difference between the nodes, or
offset
, in microseconds).
|
17.3.1. Two-way travel time ranging
The range measurement above used TWTT ranging. While node B participated in the range measurement by responding to node A’s request for a two-way frame exchange, this is all done quietly and we see nothing on node B’s shell. To see what is happening on both nodes, subscribe to the
phy
and
ranging
agent’s topics on both nodes. Then repeat the
RangeReq
on node A:
> subscribe phy
> subscribe ranging
> ranging << new RangeReq(to: host('B'))
AGREE
phy >> TxFrameStartNtf:INFORM[type:DATA txTime:2048652195 txDuration:700]
phy >> RxFrameStartNtf:INFORM[type:DATA rxTime:2051086032]
phy >> RxFrameNtf:INFORM[type:DATA from:31 to:232 protocol:1 rxTime:2051086032 txTime:526951606 (7 bytes)]
ranging >> RangeNtf:INFORM[from:232 to:31 range:371.08856 offset:-1523892589 rxTime:2051086032]
We see that node A transmitted a DATA frame. It then received a timestamped DATA frame back from node B. The timing information in both frames was used to compute the range and time offset between the nodes. This was sent back to us as a
RangeNtf
. This is the frame exchange that implements TWTT ranging.
If we look at node B’s shell at the same time:
> subscribe phy
> subscribe ranging
phy >> RxFrameStartNtf:INFORM[type:DATA rxTime:525001443]
phy >> RxFrameNtf:INFORM[type:DATA from:232 to:31 protocol:1 rxTime:525001443 (1 byte)]
ranging >> InterrogationNtf:INFORM[type:DATA from:232 to:31 rxTime:525001443 responded:true]
phy >> TxFrameStartNtf:INFORM[type:DATA txTime:526951606 txDuration:700]
We see that node B received a DATA frame and responded back with a DATA frame. It generated a
InterrogationNtf
with
responded
set to
true
to indicate that it received an interrogation and responded to it. This is because
ranging.respond = true
, as seen above. If
ranging.respond
was set to
false
, the agent would have simply generated the
InterrogationNtf
without responding. This allows another agent to study the intorrogation, and optionally send back payload data as part of the response, using the
RespondReq
message.
17.3.2. Synchronization
We can ask node A for the synchronization information it has gathered from previous ranging exchanges:
> ranging[host('B')]
« RANGING »
[org.arl.unet.localization.RangingNodeParam]
address ⤇ 31
channel = 2
data = []
ipreamble = 0
isignal = []
lastSync ⤇ 1586070856974
lifetime = 0
maxRange = 3000.0
offset = -1523892589
rdelay = 1.95
rpreamble = 0
rsignal = []
sync ⤇ false
threshold = 0.3
We see that it has stored the time offset to node B, along with the information on when the synchronization information was last updated. However, you’ll find that the
sync
flag is
false
, since the
lifetime
parameter was set to 0, and hence the synchronization is considered expired. If you ask for synchronization information on node B, you’ll find that it does not have any:
> ranging[host('A')]
« RANGING »
[org.arl.unet.localization.RangingNodeParam]
address ⤇ 232
channel = 2
data = []
ipreamble = 0
isignal = []
lastSync ⤇ 0
lifetime = 0
maxRange = 3000.0
offset = 0
rdelay = 1.95
rpreamble = 0
rsignal = []
sync ⤇ false
threshold = 0.3
Without synchronization information, OWTT ranging cannot be performed.
If we have low-drift clocks on all our nodes, we can set the
lifetime
parameter for all the links to a larger value. Let’s do that on node A for link A-B. Also unsubscribe from
phy
to avoid too much clutter:
> ranging[host('B')].lifetime = 3600
3600
> unsubscribe phy
Now check the synchronization information for link A-B again:
> ranging[host('B')]
« RANGING »
[org.arl.unet.localization.RangingNodeParam]
address ⤇ 31
channel = 2
data = []
ipreamble = 0
isignal = []
lastSync ⤇ 1586070856974
lifetime = 0
maxRange = 3000.0
offset = -1523892589
rdelay = 1.95
rpreamble = 0
rsignal = []
sync ⤇ true (1)
threshold = 0.3
1 |
We see that
sync
is now true, indicating that we have valid synchronization information on this link.
|
17.3.3. One-way travel time ranging
Now, let’s transmit a ranging beacon from node B:
> beacon // equivalent to: ranging << new BeaconReq()
AGREE
On node A, we see
RangeNtf
from the OWTT ranging:
ranging >> RangeNtf:INFORM[from:232 to:31 range:371.08856 rxTime:1039174911]
Any timestamped frame transmission from node B will generate
RangeNtf
on node A now. This can be used to piggyback data (e.g. 42) along with the beacon:
phy << new TxFrameReq(timestamped: true, data: [42])
. This will generate a
RxFrameNtf
on node A, if you subscribe to
phy
, in addition to the
RangeNtf
messages. This works with both CONTROL and DATA frames.
|
17.3.4. Ranging to COTS transponders
The ranging agent provides a lot of flexibility for configuration. To see the power of this, let’s consider a scenario in which we want to use a UnetStack-based modem to measure range to a COTS transponder that is configured to respond to a 22 kHz 2 ms long pulse with a 30 kHz 2 ms pulse, after a delay of 30 ms.
The example below is meant to run on a UnetStack-based modem. If you don’t have one, you can still try out the example on Unet audio and hear the interrogation pulse. However, because the default operating band of Unet audio SDOAM is 6-18 kHz, you’ll need to pick interrogation and response frequencies in this band. Also, you may want to make the interrogation pulse longer (say 200 ms), so you can hear it when you try ranging with this in air. |
First, we welcome the COTS transponder into our network as a Unet
guest
node by assigning it a name and address. Let’s call it node T with address
host('T') = 152
. On our modem node, we set up details of the link to the transponder:
> T = host('T')
152
> ranging[T].isignal = cw(22.kHz, 2.ms);
> ranging[T].rsignal = cw(30.kHz, 2.ms);
> ranging[T].rdelay = 30.ms;
> ranging
« RANGING »
[org.arl.unet.localization.RangingNodeParam]
address ⤇ 152
channel = 2
data = []
ipreamble = 0
isignal = [0.0, -0.0, 0.8660254, -0.5, 0.5 ... 0.5, 0.8660254, 0.8660254, 0.5]
lastSync ⤇ 0
lifetime = 0
maxRange = 3000.0
offset = 0
rdelay = 0.03
rpreamble = 0
rsignal = [0.0, 0.0, 6.123234E-17, 1.0, -1 ... 6022E-15, -3.1847007E-15, -1.0]
sync ⤇ false
threshold = 0.3
Now, we are all setup. To range to the transponder, all we need to do is:
> range T
235.7
Assuming you have the UnetStack-based modem in the water, along with the COTS transponder, you’ll get a range estimate back after just a short delay.
We have hardly scratched the surface of what the RANGING service and the ranging agent is capable of. There’s a lot you can do with it!
For an example of how to build a simple long-baseline (LBL) navigation system with multiple nodes connected over wormholes amd ranging to a mobile node, see Chapter 11 . |
<<< [Baseband service] | [Node information] >>> |