16. Ranging and synchronization
It is common to use underwater acoustic modems for range estimation, as the travel time of acoustic signals can easily be measured. In
, we saw that we can use the
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 provides messages and parameters to support OWTT and TWTT ranging, and to manage synchronization information between the nodes.
The following messages are defined by the RANGING service:
FAILURE— measure range to peer node via OWTT or TWTT
FAILURE— transmit beacon message for OWTT
FAILURE— clear synchronization information for peer node
RangeNtf— sent to agent’s topic when range information for peer node becomes available
BadRangeNtf— sent to agent’s topic when invalid range information for peer node indicates potentially outdated synchronization with that node
The use of these messages will become clearer through examples below.
A few parameters control the behavior of the RANGING service provider:
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.
The minimum and maximum valid range settings control what the RANGING service considers to be a
— a range measurement that is unlikely to occur in reality (e.g. negative values, or ranges much further than the communication ability of the modems). Frequent bad ranges to a node are used to detect that the node synchronization information is invalid and should be discarded. The number of
before discarding the synchronization information is specified as
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 (
). Start the simulation, and connect to node A:
> agentsForService(org.arl.unet.Services.RANGING) (1) [ranging] > ranging <<< Ranging >>> [org.arl.unet.phy.RangeParam] channel = 1 (2) lifetime = 0 (3) maxBadRangeCnt = 10 maxRange = 6500.0 minRange = -10.0 > range host('B') (4) 370.98 > ranging << new RangeReq(to: host('B')) (5) AGREE ranging >> RangeNtf:INFORM[from:31 to:232 range:371.0 offset:-256067128] > ntf.range (6) 370.98
We see that the
|2||The CONTROL channel (channel 1) is being used for ranging.|
16.2.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
agent’s topics on both nodes. Then repeat the
on node A:
> subscribe phy > subscribe ranging > ranging << new RangeReq(to: host('B')) AGREE phy >> TxFrameStartNtf:INFORM[type:CONTROL txTime:2546485580 txDuration:950] phy >> RxFrameStartNtf:INFORM[type:CONTROL rxTime:2548827417] phy >> RxFrameNtf:INFORM[type:CONTROL from:31 to:232 protocol:1 rxTime:2548827417 txTime:2292518452 (7 bytes)] ranging >> RangeNtf:INFORM[from:31 to:232 range:371.0 offset:-256067128]
We see that node A transmitted a CONTROL frame. It then received a timestamped CONTROL 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
. 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:CONTROL rxTime:2290660289] phy >> RxFrameNtf:INFORM[type:CONTROL from:232 to:31 protocol:1 rxTime:2290660289 (1 byte)] phy >> TxFrameStartNtf:INFORM[type:CONTROL txTime:2292518452 txDuration:950]
We see that node B received a CONTROL frame and responded back with a CONTROL frame.
We can ask node A for the synchronization information it has gathered:
> ranging << new SyncInfoReq(to: host('B')) SyncInfoRsp:INFORM[to:31 offset:-256067128 validTill:1568557167512]
We see that it has stored the time offset to node B, along with a validity. However, you’ll find that the validity has already expired, since the
parameter was set to 0. If you ask for synchronization information on node B, you’ll find that it does not have any:
> ranging << new SyncInfoReq(to: host('A')) REFUSE: Information unavailable
Without synchronization information, OWTT ranging cannot be performed.
If we have low-drift clocks on all our nodes, we can set the
parameter of the
agent to a larger value. Let’s do that on all nodes. Also unsubscribe from
to avoid too much clutter, but ensure that you’re subscribed to
on all 3 nodes (node A, node B and node C):
> ranging.lifetime = 3600 3600 > unsubscribe phy > subscribe ranging
Now, initiate TWTT ranging to from node A to node B again:
> ranging << new RangeReq(to: host('B')) AGREE ranging >> RangeNtf:INFORM[from:31 to:232 range:371.0 offset:-256067128]
Not much of a difference here, but if you look at the shell for node B, you’ll see a notification:
ranging >> RangeNtf:INFORM[from:232 to:31 range:371.0 offset:256067128]
The information in this
is the same as the
on node A, except that the
fields are exchanged, and the
has the opposite sign. This makes sense, since the
on node B is from node B’s perspective.
But why did node B receive this
? If we did a TWTT from node A, node A transmitted a frame, node B responded, and node A computed the two-way travel time. How did node B get that information to generate the
? Now that the
is non-zero, node A transmits the range and time offset to node B to synchronize the nodes. We can verify this by asking node B for the synchronization information it has gleaned:
> ranging << new SyncInfoReq(to: host('A')) SyncInfoRsp:INFORM[to:232 offset:256067128 validTill:1568562001976]
In fact, if you look at the shell for node C, you’ll see that it hears this information as well, but it does not have any synchronization information to either node A or B:
> ranging << new SyncInfoReq(to: host('A')) REFUSE: Information unavailable > ranging << new SyncInfoReq(to: host('B')) REFUSE: Information unavailable
Let’s try TWTT ranging from node A to node C:
> ranging << new RangeReq(to: host('C')) AGREE ranging >> RangeNtf:INFORM[from:74 to:232 range:529.9 offset:630715082]
Now, if you check node C, you’ll see that it has not only gotten the
, but also has stored the synchronization information:
ranging >> RangeNtf:INFORM[from:232 to:74 range:529.9 offset:-630715082] > ranging << new SyncInfoReq(to: host('A')) SyncInfoRsp:INFORM[to:232 offset:-630715082 validTill:1568562266302]
Checking node B, we find that it has also heard the exchange between nodes A and C, and gotten a
for it. More interestingly, it has synchronization information (time offset) for node C, although we did not ever do a TWTT exchange between nodes B and C! It has inferred the time offset to node C because it knew the time offset to node A, and overheard the time offset between node A and node C!
ranging >> RangeNtf:INFORM[from:74 to:232 range:529.9] > ranging << new SyncInfoReq(to: host('C')) SyncInfoRsp:INFORM[to:74 offset:886782210 validTill:1568562266192]
Based on two TWTT exchanges, node A knows time offset to nodes B and C, node B knows time offset to nodes A and C, node C knows time offet to node A. Now that we have the nodes somewhat synchronized, we are in a position to try out OWTT now.
16.2.3. One-way travel time ranging
Let’s transmit a ranging beacon from node A:
> ranging << new BeaconReq() AGREE
On node B and C, we see
from the OWTT ranging:
ranging >> RangeNtf:INFORM[from:232 to:31 range:371.0]
ranging >> RangeNtf:INFORM[from:232 to:74 range:529.9]
Any timestamped frame transmission from node A will generate
We can also get node A to request node C to transmit a beacon:
> ranging << new RangeReq(to: host('C'), reqBeacon: true) AGREE ranging >> RangeNtf:INFORM[from:74 to:232 range:529.9]
This yeilds a
back on node A, giving range from node C to node A. But since node B hears the beacon, and has synchronization information for node C, it also produces a
with the range from node C to node B:
ranging >> RangeNtf:INFORM[from:74 to:31 range:615.9]
Once you have network time synchronization, you can have a lot of fun with OWTT ranging and beacons!
16.2.4. Expired synchronization information
What happens once synchronization information expires? Does the
agent no longer get the OWTT
messages are still produced, but the message attribute
is set to
. This attribute can be used by client agents to initiate a TWTT exchange to renew synchronization information, if necessary. So, if you work with OWTT ranging, remember to check the
messages that you receive, to ensure that they are based on unexpired synchronization information and therefore accurate.
|<<< [Baseband service]||[Node information] >>>|