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 to RangeReq on current node (sent to requester), or BeaconReq 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:

  • phy — physical agent to use for ranging

  • mac — MAC agent to use for channel reservations

  • respond — true if the agent should automatically respond to interrogation frames from peers, false if it should generate a InterrogationNtf and wait for another agent to request a response using RespondReq

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.

Why do clocks drift?

Most electronics use crystal oscillators for timekeeping. A crystal oscillator is an electronic circuit that uses the mechanical resonance of a vibrating piezoelectric crystal to create an electrical signal with a desired frequency. The resonant frequency depends on size, shape, elasticity, and the speed of sound in the material. Due to manufacturing tolerences, these properties are not exactly identical across manufactured crystals, and so different crystals designed for the same nominal frequency produce slightly different frequency signals. Furthermore, as the operating temperature of the crystal changes, its material properties change, and so does its resonant frequency. These differences in frequency are tiny, but over long periods of time, the differences accumulate and cause the clocks to drift.

For applications where drift is undesirable, temperature-compensated crystal oscillators (TCXO) or oven-controlled crystal oscillators (OCXO) may be used. TCXOs try to adjust their oscillation frequency electronically, to compensate for temperature changes. OCXOs, on the other hand, try to maintain a constant temperature with a mini-oven around the crystal. For very sensitive applications, atomic clocks may be used for even lower drift. But given long enough time, even the most precise of these oscillators will accumulate tiny errors and the clocks will eventually drift!

A few more read-only per-link parameters provide synchronization information about the link, when available:

  • sync — availability of synchronization information on link

  • lastSync — time of last synchronization (epoch milliseconds)

  • offset — clock offset between current node and peer node (microseconds)

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:

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:

Node B:
> 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:

Node A:
> 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:

Node B:
> 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:

Nodes A:
> ranging[host('B')].lifetime = 3600
3600
> unsubscribe phy

Now check the synchronization information for link A-B again:

Node A:
> 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:

Node B
> beacon      // equivalent to: ranging << new BeaconReq()
AGREE

On node A, we see RangeNtf from the OWTT ranging:

Node A
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] >>>