Single Sided Two Way Ranging - Constant distance offset
cmb87 opened this issue · 0 comments
Hello everyone,
I'm trying to implement a custom version of single sided two way ranging (which only requires two frames per range measurement) for peer ranging. My inspiration is this example: https://github.com/Decawave/dwm1001-examples/blob/master/examples/ss_twr_resp/main.c. The UWB nodes change from responder to initiator and vice versa after each successful ranging transaction.
I currently observe a constant range error, no matter how much I tune the antenna delay parameter. So for a given cycle
I see:
Node 1 to Node 2: 0.6m Node2 to Node 1: 6.6m (both are approx 1m apart)
After changing the antenna delay I get (no matter how I change it):
Node 1 to Node 2: -5.6m Node2 to Node 1: 1.6m (both are approx 1m apart)
There is this constant offset, which I cannot explain. I use the Makerfabs ESP32 UWB D1000 module with PlatformIO.
On the initiator side, I wrote a function which uses this snippet and after the sending, I store the transmit timestamp.
DW1000.newTransmit();
DW1000.setDefaults();
data[INIT_ID_POS] = UWB_NODE_ID;
data[RCVR_ID_POS] = responderId;
data[MSGT_ID_POS] = MSGT_INIT;
DW1000.setData(data, UWB_BUFFER_SIZE);
DW1000.startTransmit();
On the responder side I store the receive timestamp and respond to the receiver, like so
DW1000.newTransmit();
DW1000.setDefaults();
// delay the same amount as ranging tag
DW1000Time deltaTime = DW1000Time(REPLAYDELAYTIMEUS, DW1000Time::MICROSECONDS);
timeResponderTransmit = DW1000.setDelay(deltaTime, true);
data[INIT_ID_POS] = initiatorId;
data[RCVR_ID_POS] = UWB_NODE_ID;
data[MSGT_ID_POS] = MSGT_RESP;
timeResponderReceive.getTimestamp(data + RX_TIMESTAMP_START_POS);
timeResponderTransmit.getTimestamp(data + TX_TIMESTAMP_START_POS);
DW1000.setData(data, UWB_BUFFER_SIZE);
DW1000.startTransmit();
Upon reception on the initiator side, I use below's snippet to compute the distance
timeResponderReceive.setTimestamp(data + RX_TIMESTAMP_START_POS);
timeResponderTransmit.setTimestamp(data + TX_TIMESTAMP_START_POS);
DW1000Time rtd_init = (timeInitiatorReceive - timeInitiatorTransmit).wrap();
DW1000Time rtd_resp = (timeResponderTransmit - timeResponderReceive).wrap();
DW1000Time tof = (rtd_init - rtd_resp )* 0.5f;
float distance = tof.getAsMeters();
My buffer has the size of 31 bytes and REPLAYDELAYTIMEUS is 4000. I noticed that the Decawave example uses these lines of code for the delayed send on the responder side.
/* Compute final message transmission time. See NOTE 7 below. */
resp_tx_time = (poll_rx_ts + (POLL_RX_TO_RESP_TX_DLY_UUS * UUS_TO_DWT_TIME)) >> 8;
dwt_setdelayedtrxtime(resp_tx_time);
/* Response TX timestamp is the transmission time we programmed plus the antenna delay. */
resp_tx_ts = (((uint64)(resp_tx_time & 0xFFFFFFFEUL)) << 8) + TX_ANT_DLY;
Comparison with in the DW1000.cpp concluded to me that these functions are equivalent with the setDelay method. Does anyone have a thought what might be going wrong here? I noticed Decawave uses
tof = ((rtd_init - rtd_resp * (1.0f - clockOffsetRatio)) / 2.0f) * DWT_TIME_UNITS
and I transferred this function to the DW1000 lib, but didn't see an effect at all.
Thank you.