This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

BOOSTXL-AOA: Giving Angle data instead of IQ samples

Part Number: BOOSTXL-AOA

Hi,

I have changed the mode as AOA_MODE_RAW in python file, attached below still i am getting the angle data.

I have made the changes in npi task.c file as mentioned in Task 4

To achieve this, there are two options:

  1. Increase the connection interval. In the rtls_master readme file, it's mentioned that the connection interval should be larger than 300ms to acommodate outputting all the samples.

  2. Increase the UART baurate to 2x, 4x or 8x 115200.

    To achieve this, navigate to source/ti/blestack/npi/src/unified/npi_task.c::uint8_t NPITask_Params_init(uint8_t portType, NPI_Params *params) and add the following under the #if defined(NPI_USE_UART)

    After making these changes, still i am getting angle as results

Please suggest me how to obtain those

Code:

import queue
import csv
import time
from collections import namedtuple
from rtls import RTLSManager, RTLSNode

# Un-comment the below to get raw serial transaction logs
# import logging, sys
# logging.basicConfig(stream=sys.stdout, level=logging.DEBUG,
# format='[%(asctime)s] {%(filename)s:%(lineno)d} %(levelname)s - %(message)s')

if __name__ == '__main__':
# Initialize, but don't start RTLS Nodes to give to the RTLSManager
my_nodes = [RTLSNode('COM17', 115200), RTLSNode('COM9', 115200)]

# Prepare csv file to save data
filename = 'rtls_raw_iq_samples.csv'
outfile = open(filename, 'w', newline='')

csv_fieldnames = ['pkt', 'sample_idx', 'rssi', 'ant_array', 'channel', 'i', 'q']
SampleRow = namedtuple('CsvRow', csv_fieldnames)

csv_writer = csv.DictWriter(outfile, fieldnames=csv_fieldnames)
csv_writer.writeheader()

# Temporary storage of iq samples
dump_rows = []

# How many AoA sample buffers should be stored.
# None means infinite. Press Ctrl+C to terminate in this case.
pkt_limit = 200 # None # 5

# Running packet counter
pkt_cnt = 0

# Initialize references to the connected devices
master_node = None
passive_nodes = []
# Initialize references to the connected devices
address = None
address_type = None

# ToF related settings
samples_per_burst = 256 # Should be a power of 2. Hint: in a 100ms interval, there are about 300~ samples
tof_freq_list = [2408, 2412, 2418, 2424] #Other options: 2414, 2420
tof_num_freq = len(tof_freq_list)
auto_tof_rssi = -55
tof_sample_mode = 'TOF_MODE_DIST'
tof_run_mode = 'TOF_MODE_CONT'
seed = 0
samplesPerFreq = 1000
calibDistance = 1 # 1 meter

# AoA related settings
aoa_run_mode = 'AOA_MODE_RAW'
aoa_cte_scan_ovs = 4
aoa_cte_offset = 4
aoa_cte_time = 20

# Auto detect AoA or ToF support related
tof_supported = False
aoa_supported = False

# If slave addr is None, the script will connect to the first RTLS slave
# that it found. If you wish to connect to a specific device
# (in the case of multiple RTLS slaves) then you may specify the address
# explicitly as given in the comment to the right
slave_addr = None #'54:6C:0E:A0:47:43'

# Initialize manager reference, because on Exception we need to stop the manager to stop all the threads.
manager = None
try:
# Start an RTLSManager instance without WebSocket server enabled
manager = RTLSManager(my_nodes, websocket_port=None)
# Create a subscriber object for RTLSManager messages
subscriber = manager.create_subscriber()
# Tell the manager to automatically distribute connection parameters
manager.auto_params = True
# Start RTLS Node threads, Serial threads, and manager thread
manager.start()

# Wait until nodes have responded to automatic identify command and get reference
# to single master RTLSNode and list of passive RTLSNode instances
master_node, passive_nodes, failed = manager.wait_identified()

if len(failed):
print(f"ERROR: {len(failed)} nodes could not be identified. Are they programmed?")

# Exit if no master node exists
if not master_node:
raise RuntimeError("No RTLS Master node connected")

# Combined list for lookup
all_nodes = passive_nodes + [master_node]

# Initialize application variables on nodes
for node in all_nodes:
node.tof_initialized = False
node.seed_initialized = False
node.aoa_initialized =True

#
# At this point the connected devices are initialized and ready
#

# Display list of connected devices and their capabilities
print(f"{master_node.identifier} {', '.join([cap for cap, available in master_node.capabilities.items() if available])}")

# Iterate over Passives and detect their capabilities
for pn in passive_nodes:
print(f"{pn.identifier} {', '.join([cap for cap, available in pn.capabilities.items() if available])}")

# Check over aggregated capabilities to see if they make sense
capabilities_per_node = [[cap for cap, avail in node.capabilities.items() if avail] for node in all_nodes]
tof_supported = all('TOF_PASSIVE' in node_caps or 'TOF_MASTER' in node_caps for node_caps in capabilities_per_node)

# Assume AoA if all nodes are not ToF
aoa_supported = all(not ('TOF_PASSIVE' in node_caps or 'TOF_MASTER' in node_caps) for node_caps in capabilities_per_node)

# Check that Nodes all must be either AoA or ToF
if not (tof_supported or aoa_supported):
raise RuntimeError("All nodes must be either AoA or ToF")

# Need at least 1 passive for AoA
if aoa_supported and len(passive_nodes) == 0:
raise RuntimeError('Need at least 1 passive for AoA')

# Send an example command to each of them, from commands listed at the bottom of rtls/ss_rtls.py
for n in all_nodes:
n.rtls.identify()

while True:
# Get messages from manager
try:
identifier, msg_pri, msg = subscriber.pend(block=True, timeout=0.05).as_tuple()

# Get reference to RTLSNode based on identifier in message
sending_node = manager[identifier]

if sending_node in passive_nodes:
print(f"PASSIVE: {identifier} --> {msg.as_json()}")
else:
print(f"MASTER: {identifier} --> {msg.as_json()}")

# If we received an assert, print it.
if msg.command == 'UTIL_NPI_HW_ASSERT' and msg.type == 'AsyncReq':
raise RuntimeError(f"Received HCI H/W Assert with code: {msg.payload.subcause}")

# After identify is received, we start scanning
if msg.command == 'RTLS_CMD_IDENTIFY':
master_node.rtls.scan()

# Once we start scaning, we will save the address of the
# last scan response
if msg.command == 'RTLS_CMD_SCAN' and msg.type == 'AsyncReq':
address = msg.payload.addr
address_type = msg.payload.addrType

# Once the scan has stopped and we have a valid address, then
# connect
if msg.command == 'RTLS_CMD_SCAN_STOP':
if address is not None and address_type is not None and (slave_addr is None or slave_addr == address):
master_node.rtls.connect(address_type, address)
else:
# If we didn't find the device, keep scanning.
master_node.rtls.scan()

# Once we are connected, then we can do stuff
if msg.command == 'RTLS_CMD_CONNECT' and msg.type == 'AsyncReq':
if msg.payload.status == 'RTLS_SUCCESS':
if tof_supported:
# Find the role based on capabilities of sending node
role = 'TOF_MASTER' if sending_node.capabilities.get('TOF_MASTER', False) else 'TOF_PASSIVE'
# Send the ToF parameters to the node that just connected
sending_node.rtls.tof_set_params(role, samples_per_burst,
tof_num_freq, auto_tof_rssi,
tof_sample_mode, tof_run_mode,
tof_freq_list)

if aoa_supported:
# Find the role based on capabilities of sending node
role = 'AOA_MASTER' if sending_node.capabilities.get('AOA_MASTER', False) else 'AOA_PASSIVE'
# Send AoA params
sending_node.rtls.aoa_set_params(role, aoa_run_mode,
aoa_cte_scan_ovs,
aoa_cte_offset,
aoa_cte_time)
else:
# If the connection failed, keep scanning
master_node.rtls.scan()

# Count the number of nodes that have ToF initialized
if msg.command == 'RTLS_CMD_TOF_SET_PARAMS' and msg.payload.status == 'RTLS_SUCCESS':
sending_node.tof_initialized = True

# If all nodes have responded then we are ready to move on
if all([n.tof_initialized for n in all_nodes]):
# Send request for seed to master
master_node.rtls.tof_get_sec_seed()

if msg.command == 'RTLS_CMD_AOA_SET_PARAMS' and msg.payload.status == 'RTLS_SUCCESS':
sending_node.aoa_initialized = True
if all([n.aoa_initialized for n in all_nodes]):
# Start AoA on the master and passive nodes
for node in all_nodes:
node.rtls.aoa_start(True)


# Wait for security seed
if msg.command == 'RTLS_CMD_TOF_GET_SEC_SEED' and msg.payload.seed is not 0:
seed = msg.payload.seed
for node in passive_nodes:
node.rtls.tof_set_sec_seed(seed)

# Wait until passives have security seed set and start ToF
if msg.command == 'RTLS_CMD_TOF_SET_SEC_SEED' and msg.payload.status == 'RTLS_SUCCESS':
sending_node.seed_initialized = True

if all([n.seed_initialized for n in passive_nodes]):
for node in passive_nodes:
node.rtls.tof_start(True)

# Passive must start well before Master does since it must "hear" the first ToF exchange
master_node.rtls.tof_start(True)

# Wait until passives have security seed set. Set calibration option
if msg.command == 'RTLS_CMD_TOF_ENABLE' and msg.payload.status == 'RTLS_SUCCESS':

# Only need to calibrate in distance mode
if tof_sample_mode == 'TOF_MODE_DIST':
if sending_node in passive_nodes:
for node in passive_nodes:
node.rtls.tof_calib(True, samplesPerFreq, calibDistance)
else:
master_node.rtls.tof_calib(True, samplesPerFreq, calibDistance)

# Saving I/Q samples into csv file
if msg.command == 'RTLS_CMD_AOA_RESULT_RAW':
payload = msg.payload
# Extract first sample index in this payload
offset = payload.offset

# If we have data, and offset is 0, we are done with one dump
if offset == 0 and len(dump_rows):
pkt_cnt += 1

# Make sure the samples are in order
dump_rows = sorted(dump_rows, key=lambda s: s.sample_idx)

# Write to file
for sample_row in dump_rows:
csv_writer.writerow(sample_row._asdict())

# Reset payload storage
dump_rows = []

# Stop script now if there was a limit configured
if pkt_limit is not None and pkt_cnt > pkt_limit:
break

# Save samples for writing when dump is complete
for sub_idx, sample in enumerate(payload.samples):
sample = SampleRow(pkt=pkt_cnt, sample_idx=offset + sub_idx, rssi=payload.rssi, ant_array=payload.antenna, channel=payload.channel, i=sample.i, q=sample.q)
dump_rows.append(sample)


except queue.Empty:
pass

finally:
outfile.flush()
outfile.close()

if manager:
manager.stop()

Thanks and Regards

Akansha

  • Hello Akansha,

    I have assigned an expert to comment.

  • Hi Akansha,

    Can you precise which SDK version you are using for this project?

    Thanks and regards,

  • Hi,

    I am using SDK cc260r2_3_20_00_21.

    Currently i am getting IQ samples.

    For controlling number of IQ samples, i have made changes in following parameters:

    aoa_run_mode = 'AOA_MODE_RAW'
    aoa_cte_scan_ovs = 2
    aoa_cte_offset = 1
    aoa_cte_time = 5

    According to above values, my IQ samples should be 78.


    Still i am getting 510 IQ samples for one packet.

    Is there any other way to control number of IQ samples

  • Hi,

    One remark to begin. You have chosen a value for aoa_cte_offset that is potentially too small with regard to the AOA boosterpack (this value is supposed to be the guard time required to switch from one antenna to the other). However, this should not be a problem in a first time (you will just get potentially bad values for some of your samples).

    Can you verify for me if the parameter are properly send to the passive and master nodes? One solution could be to see if both devices are executing RTLSCtrl_setAoaParams() (line 1488 of rtls_ctrl.c, under the case "RTLS_CMD_AOA_SET_PARAMS" of the function RTLSCtrl_processHostMessage()). You can also verify if once this function has been executed the content of gRtlsData.aoaControlBlock.aoaParams is correct.

    Then you can verify in rtls_ctrl_aoa.c if the number of  samples outputted is correct. To do so, please have a look to the function RTLSCtrl_postProcessAoa() (in rtls_ctrl_aoa.c). In the case "AOA_MODE_RAW", the number of samples outputted is given by the function AOA_calcNumOfCteSamples() (line 228).

    Regards,

  • Hi

    Thanks for the descriptive reply.

    Currently i am facing following problems:

    1. Sometimes the same python script provide me the IQ samples and sometimes it started providing me the AOA along with RSSI values. When it is providing the angle data then it is executing  RTLS_CMD_AOA_RESULT in place of RTLS_CMD_AOA_RESULT_RAW command.

    2. When i applied algorithm to obtain the AOA from IQ samples obtained, it is giving unnecessary values: file is attached below:

    Python Script log:

    Python 3.7.4 (tags/v3.7.4:e09359112e, Jul  8 2019, 19:29:22) [MSC v.1916 32 bit (Intel)] on win32
    Type "help", "copyright", "credits" or "license()" for more information.
    >>> 
     RESTART: C:\ti\simplelink_cc2640r2_sdk_3_20_00_21\tools\blestack\rtls_agent\examples\Edit.py 
    54:6C:0E:83:6E:5C AOA_RX, RTLS_MASTER
    B0:91:22:69:F4:46 CM, AOA_RX, RTLS_PASSIVE
    PASSIVE: B0:91:22:69:F4:46 --> {"originator": "Nwp", "type": "AsyncReq", "subsystem": "RTLS", "command": "RTLS_CMD_AOA_RESULT_ANGLE", "payload": {"angle": 71, "rssi": -58, "antenna": 1, "channel": 32}}
    MASTER: 54:6C:0E:83:6E:5C --> {"originator": "Nwp", "type": "SyncRsp", "subsystem": "RTLS", "command": "RTLS_CMD_IDENTIFY", "payload": {"capabilities": {"CM": false, "AOA_TX": false, "AOA_RX": true, "TOF_SLAVE": false, "TOF_PASSIVE": false, "TOF_MASTER": false, "RTLS_SLAVE": false, "RTLS_MASTER": true, "RTLS_PASSIVE": false}, "identifier": "54:6C:0E:83:6E:5C"}}
    PASSIVE: B0:91:22:69:F4:46 --> {"originator": "Nwp", "type": "SyncRsp", "subsystem": "RTLS", "command": "RTLS_CMD_IDENTIFY", "payload": {"capabilities": {"CM": true, "AOA_TX": false, "AOA_RX": true, "TOF_SLAVE": false, "TOF_PASSIVE": false, "TOF_MASTER": false, "RTLS_SLAVE": false, "RTLS_MASTER": false, "RTLS_PASSIVE": true}, "identifier": "B0:91:22:69:F4:46"}}
    PASSIVE: B0:91:22:69:F4:46 --> {"originator": "Nwp", "type": "AsyncReq", "subsystem": "RTLS", "command": "RTLS_CMD_AOA_RESULT_ANGLE", "payload": {"angle": 70, "rssi": -60, "antenna": 1, "channel": 17}}
    MASTER: 54:6C:0E:83:6E:5C --> {"originator": "Nwp", "type": "SyncRsp", "subsystem": "RTLS", "command": "RTLS_CMD_SCAN", "payload": {"status": "RTLS_SUCCESS"}}
    MASTER: 54:6C:0E:83:6E:5C --> {"originator": "Nwp", "type": "SyncRsp", "subsystem": "RTLS", "command": "RTLS_CMD_SCAN", "payload": {"status": "RTLS_SUCCESS"}}
    PASSIVE: B0:91:22:69:F4:46 --> {"originator": "Nwp", "type": "AsyncReq", "subsystem": "RTLS", "command": "RTLS_CMD_AOA_RESULT_ANGLE", "payload": {"angle": 69, "rssi": -58, "antenna": 1, "channel": 2}}
    PASSIVE: B0:91:22:69:F4:46 --> {"originator": "Nwp", "type": "AsyncReq", "subsystem": "RTLS", "command": "RTLS_CMD_AOA_RESULT_ANGLE", "payload": {"angle": 71, "rssi": -60, "antenna": 1, "channel": 24}}
    PASSIVE: B0:91:22:69:F4:46 --> {"originator": "Nwp", "type": "AsyncReq", "subsystem": "RTLS", "command": "RTLS_CMD_AOA_RESULT_ANGLE", "payload": {"angle": 69, "rssi": -59, "antenna": 1, "channel": 9}}
    PASSIVE: B0:91:22:69:F4:46 --> {"originator": "Nwp", "type": "AsyncReq", "subsystem": "RTLS", "command": "RTLS_CMD_AOA_RESULT_ANGLE", "payload": {"angle": 69, "rssi": -58, "antenna": 1, "channel": 31}}
    PASSIVE: B0:91:22:69:F4:46 --> {"originator": "Nwp", "type": "AsyncReq", "subsystem": "RTLS", "command": "RTLS_CMD_AOA_RESULT_ANGLE", "payload": {"angle": 69, "rssi": -60, "antenna": 1, "channel": 16}}
    PASSIVE: B0:91:22:69:F4:46 --> {"originator": "Nwp", "type": "AsyncReq", "subsystem": "RTLS", "command": "RTLS_CMD_AOA_RESULT_ANGLE", "payload": {"angle": 69, "rssi": -58, "antenna": 1, "channel": 1}}
    PASSIVE: B0:91:22:69:F4:46 --> {"originator": "Nwp", "type": "AsyncReq", "subsystem": "RTLS", "command": "RTLS_CMD_AOA_RESULT_ANGLE", "payload": {"angle": 70, "rssi": -58, "antenna": 1, "channel": 34}}
    PASSIVE: B0:91:22:69:F4:46 --> {"originator": "Nwp", "type": "AsyncReq", "subsystem": "RTLS", "command": "RTLS_CMD_AOA_RESULT_ANGLE", "payload": {"angle": 70, "rssi": -60, "antenna": 1, "channel": 19}}
    PASSIVE: B0:91:22:69:F4:46 --> {"originator": "Nwp", "type": "AsyncReq", "subsystem": "RTLS", "command": "RTLS_CMD_AOA_RESULT_ANGLE", "payload": {"angle": 69, "rssi": -58, "antenna": 1, "channel": 4}}
    PASSIVE: B0:91:22:69:F4:46 --> {"originator": "Nwp", "type": "AsyncReq", "subsystem": "RTLS", "command": "RTLS_CMD_AOA_RESULT_ANGLE", "payload": {"angle": 71, "rssi": -59, "antenna": 1, "channel": 26}}
    PASSIVE: B0:91:22:69:F4:46 --> {"originator": "Nwp", "type": "AsyncReq", "subsystem": "RTLS", "command": "RTLS_CMD_AOA_RESULT_ANGLE", "payload": {"angle": 67, "rssi": -60, "antenna": 1, "channel": 11}}
    PASSIVE: B0:91:22:69:F4:46 --> {"originator": "Nwp", "type": "AsyncReq", "subsystem": "RTLS", "command": "RTLS_CMD_AOA_RESULT_ANGLE", "payload": {"angle": 68, "rssi": -58, "antenna": 1, "channel": 33}}
    PASSIVE: B0:91:22:69:F4:46 --> {"originator": "Nwp", "type": "AsyncReq", "subsystem": "RTLS", "command": "RTLS_CMD_AOA_RESULT_ANGLE", "payload": {"angle": 67, "rssi": -58, "antenna": 1, "channel": 29}}
    PASSIVE: B0:91:22:69:F4:46 --> {"originator": "Nwp", "type": "AsyncReq", "subsystem": "RTLS", "command": "RTLS_CMD_AOA_RESULT_ANGLE", "payload": {"angle": 65, "rssi": -60, "antenna": 1, "channel": 14}}
    PASSIVE: B0:91:22:69:F4:46 --> {"originator": "Nwp", "type": "AsyncReq", "subsystem": "RTLS", "command": "RTLS_CMD_AOA_RESULT_ANGLE", "payload": {"angle": 61, "rssi": -61, "antenna": 2, "channel": 10}}
    PASSIVE: B0:91:22:69:F4:46 --> {"originator": "Nwp", "type": "AsyncReq", "subsystem": "RTLS", "command": "RTLS_CMD_AOA_RESULT_ANGLE", "payload": {"angle": 60, "rssi": -59, "antenna": 1, "channel": 21}}
    PASSIVE: B0:91:22:69:F4:46 --> {"originator": "Nwp", "type": "AsyncReq", "subsystem": "RTLS", "command": "RTLS_CMD_AOA_RESULT_ANGLE", "payload": {"angle": 63, "rssi": -58, "antenna": 1, "channel": 6}}
    PASSIVE: B0:91:22:69:F4:46 --> {"originator": "Nwp", "type": "AsyncReq", "subsystem": "RTLS", "command": "RTLS_CMD_AOA_RESULT_ANGLE", "payload": {"angle": 64, "rssi": -58, "antenna": 1, "channel": 28}}
    PASSIVE: B0:91:22:69:F4:46 --> {"originator": "Nwp", "type": "AsyncReq", "subsystem": "RTLS", "command": "RTLS_CMD_AOA_RESULT_ANGLE", "payload": {"angle": 61, "rssi": -60, "antenna": 1, "channel": 13}}
    PASSIVE: B0:91:22:69:F4:46 --> {"originator": "Nwp", "type": "AsyncReq", "subsystem": "RTLS", "command": "RTLS_CMD_AOA_RESULT_ANGLE", "payload": {"angle": 63, "rssi": -58, "antenna": 1, "channel": 35}}
    PASSIVE: B0:91:22:69:F4:46 --> {"originator": "Nwp", "type": "AsyncReq", "subsystem": "RTLS", "command": "RTLS_CMD_AOA_RESULT_ANGLE", "payload": {"angle": 68, "rssi": -59, "antenna": 1, "channel": 20}}
    PASSIVE: B0:91:22:69:F4:46 --> {"originator": "Nwp", "type": "AsyncReq", "subsystem": "RTLS", "command": "RTLS_CMD_AOA_RESULT_ANGLE", "payload": {"angle": 67, "rssi": -58, "antenna": 1, "channel": 5}}
    PASSIVE: B0:91:22:69:F4:46 --> {"originator": "Nwp", "type": "AsyncReq", "subsystem": "RTLS", "command": "RTLS_CMD_AOA_RESULT_ANGLE", "payload": {"angle": 69, "rssi": -59, "antenna": 1, "channel": 27}}
    PASSIVE: B0:91:22:69:F4:46 --> {"originator": "Nwp", "type": "AsyncReq", "subsystem": "RTLS", "command": "RTLS_CMD_AOA_RESULT_ANGLE", "payload": {"angle": 64, "rssi": -60, "antenna": 1, "channel": 12}}
    PASSIVE: B0:91:22:69:F4:46 --> {"originator": "Nwp", "type": "AsyncReq", "subsystem": "RTLS", "command": "RTLS_CMD_AOA_RESULT_ANGLE", "payload": {"angle": 67, "rssi": -58, "antenna": 1, "channel": 34}}
    PASSIVE: B0:91:22:69:F4:46 --> {"originator": "Nwp", "type": "AsyncReq", "subsystem": "RTLS", "command": "RTLS_CMD_AOA_RESULT_ANGLE", "payload": {"angle": 66, "rssi": -60, "antenna": 1, "channel": 19}}
    PASSIVE: B0:91:22:69:F4:46 --> {"originator": "Nwp", "type": "AsyncReq", "subsystem": "RTLS", "command": "RTLS_CMD_AOA_RESULT_ANGLE", "payload": {"angle": 65, "rssi": -58, "antenna": 1, "channel": 4}}
    PASSIVE: B0:91:22:69:F4:46 --> {"originator": "Nwp", "type": "AsyncReq", "subsystem": "RTLS", "command": "RTLS_CMD_AOA_RESULT_ANGLE", "payload": {"angle": 67, "rssi": -59, "antenna": 1, "channel": 26}}
    PASSIVE: B0:91:22:69:F4:46 --> {"originator": "Nwp", "type": "AsyncReq", "subsystem": "RTLS", "command": "RTLS_CMD_AOA_RESULT_ANGLE", "payload": {"angle": 61, "rssi": -60, "antenna": 1, "channel": 11}}
    PASSIVE: B0:91:22:69:F4:46 --> {"originator": "Nwp", "type": "AsyncReq", "subsystem": "RTLS", "command": "RTLS_CMD_AOA_RESULT_ANGLE", "payload": {"angle": 65, "rssi": -58, "antenna": 1, "channel": 33}}
    PASSIVE: B0:91:22:69:F4:46 --> {"originator": "Nwp", "type": "AsyncReq", "subsystem": "RTLS", "command": "RTLS_CMD_AOA_RESULT_ANGLE", "payload": {"angle": 58, "rssi": -58, "antenna": 2, "channel": 3}}
    PASSIVE: B0:91:22:69:F4:46 --> {"originator": "Nwp", "type": "AsyncReq", "subsystem": "RTLS", "command": "RTLS_CMD_AOA_RESULT_ANGLE", "payload": {"angle": 56, "rssi": -60, "antenna": 1, "channel": 14}}
    PASSIVE: B0:91:22:69:F4:46 --> {"originator": "Nwp", "type": "AsyncReq", "subsystem": "RTLS", "command": "RTLS_CMD_AOA_RESULT_ANGLE", "payload": {"angle": 56, "rssi": -58, "antenna": 1, "channel": 36}}
    PASSIVE: B0:91:22:69:F4:46 --> {"originator": "Nwp", "type": "AsyncReq", "subsystem": "RTLS", "command": "RTLS_CMD_AOA_RESULT_ANGLE", "payload": {"angle": 56, "rssi": -59, "antenna": 1, "channel": 21}}
    PASSIVE: B0:91:22:69:F4:46 --> {"originator": "Nwp", "type": "AsyncReq", "subsystem": "RTLS", "command": "RTLS_CMD_AOA_RESULT_ANGLE", "payload": {"angle": 60, "rssi": -58, "antenna": 1, "channel": 6}}
    PASSIVE: B0:91:22:69:F4:46 --> {"originator": "Nwp", "type": "AsyncReq", "subsystem": "RTLS", "command": "RTLS_CMD_AOA_RESULT_ANGLE", "payload": {"angle": 61, "rssi": -58, "antenna": 1, "channel": 28}}
    PASSIVE: B0:91:22:69:F4:46 --> {"originator": "Nwp", "type": "AsyncReq", "subsystem": "RTLS", "command": "RTLS_CMD_AOA_RESULT_ANGLE", "payload": {"angle": 66, "rssi": -60, "antenna": 1, "channel": 13}}
    PASSIVE: B0:91:22:69:F4:46 --> {"originator": "Nwp", "type": "AsyncReq", "subsystem": "RTLS", "command": "RTLS_CMD_AOA_RESULT_ANGLE", "payload": {"angle": 68, "rssi": -58, "antenna": 1, "channel": 35}}
    PASSIVE: B0:91:22:69:F4:46 --> {"originator": "Nwp", "type": "AsyncReq", "subsystem": "RTLS", "command": "RTLS_CMD_AOA_RESULT_ANGLE", "payload": {"angle": 68, "rssi": -59, "antenna": 1, "channel": 20}}
    PASSIVE: B0:91:22:69:F4:46 --> {"originator": "Nwp", "type": "AsyncReq", "subsystem": "RTLS", "command": "RTLS_CMD_AOA_RESULT_ANGLE", "payload": {"angle": 68, "rssi": -62, "antenna": 1, "channel": 5}}
    PASSIVE: B0:91:22:69:F4:46 --> {"originator": "Nwp", "type": "AsyncReq", "subsystem": "RTLS", "command": "RTLS_CMD_AOA_RESULT_ANGLE", "payload": {"angle": 70, "rssi": -59, "antenna": 1, "channel": 27}}
    PASSIVE: B0:91:22:69:F4:46 --> {"originator": "Nwp", "type": "AsyncReq", "subsystem": "RTLS", "command": "RTLS_CMD_AOA_RESULT_ANGLE", "payload": {"angle": 68, "rssi": -60, "antenna": 1, "channel": 12}}
    PASSIVE: B0:91:22:69:F4:46 --> {"originator": "Nwp", "type": "AsyncReq", "subsystem": "RTLS", "command": "RTLS_CMD_AOA_RESULT_ANGLE", "payload": {"angle": 70, "rssi": -58, "antenna": 1, "channel": 34}}
    PASSIVE: B0:91:22:69:F4:46 --> {"originator": "Nwp", "type": "AsyncReq", "subsystem": "RTLS", "command": "RTLS_CMD_AOA_RESULT_ANGLE", "payload": {"angle": 66, "rssi": -60, "antenna": 1, "channel": 19}}Traceback (most recent call last):
      File "C:\ti\simplelink_cc2640r2_sdk_3_20_00_21\tools\blestack\rtls_agent\examples\Edit.py", line 131, in <module>
        print(f"PASSIVE: {identifier} --> {msg.as_json()}")
    KeyboardInterrupt
    >>> 
    

  • Hi Akansha,

    1- This problem needs to be examined. I will do my best to have a look at it within a week (let's say before Wednesday 20th). If you have any other information or if you do any other test, please let me know. 

    2- What do you mean by "unnecessary values"? Are you referring to the columns "rssi", "ant_array"...? These columns can be removed using two ways:

    - [nicer way] by not sending them from the device to the PC. To do so, you have to modify the following line to not send the unnecessary data:

    RTLSHost_sendMsg(RTLS_CMD_AOA_RESULT_RAW, HOST_ASYNC_RSP, (uint8_t *)aoaResult, sizeof(rtlsAoaResultRaw_t) + (sizeof(AoA_IQSample) * samplesToOutput));

    Note: this code is part of the file rtls_ctrl_aoa.c, and according to the mode used you will probably want to also modify the following lines:

    // line 170
    RTLSHost_sendMsg(RTLS_CMD_AOA_RESULT_ANGLE, HOST_ASYNC_RSP, (uint8_t *)&aoaResult, sizeof(rtlsAoaResultAngle_t));
    
    // line 210
    RTLSHost_sendMsg(RTLS_CMD_AOA_RESULT_PAIR_ANGLES, HOST_ASYNC_RSP, (uint8_t *)&aoaResult, sizeof(rtlsAoaResultPairAngles_t));

    In addition, a modification of the corresponding python classes is required (in ss_rtls.py):

        class AoaResultRaw(NpiRequest, AsyncReq, FromNwp):
            command = Commands.RTLS_CMD_AOA_RESULT_RAW
            struct = Struct(
                "rssi" / Int8sl,
                "antenna" / Int8ul,
                "channel" / Int8ul,
                "offset" / Int16ul,
                "samplesLength" / Int16ul,
                "samples" / GreedyRange(Struct(
                    "q" / Int16sl,
                    "i" / Int16sl,
                )),
            )

    - [easier way] by not displaying/printing them. The following python lines will write the expected data into the result file (so you can modify it to only print what you want):

           # Save samples for writing when dump is complete
           for sub_idx, sample in enumerate(payload.samples):
               sample = SampleRow(pkt=pkt_cnt, sample_idx=offset + sub_idx, rssi=payload.rssi, ant_array=payload.antenna, channel=payload.channel, i=sample.i, q=sample.q)
               dump_rows.append(sample)

    I hope this will help,

    Regards,

  • Hi,

    Thanks for your support.

    By mentioning of unnecessary values, i mean to say the value of last column are the values of  , and we need to take inverse of sin over these values. And these value are not in range [1 to −1]. 

    Can yo please have a look on all those values which i calculated in above query.


    And please suggest me where i am doing wrong

    Thanks 

    Akansha

  • Akansha,

    What are the measure units used? An error in the conversion of the measure units or using two different units might explain why all the numbers seemed to be between -100 and +100.

    Regards,

  • Hi,

      in this formula i have used following value's units:

    Wavelength in meter


    d in meter


    phase shift is tan(phase difference ): math.tan(math.degrees(math.atan2(q_value,i_value)))

    Please suggest me if i need to make any changes in above calculations.

  • Hi,

    The phase must be in radians. I have checked the other values you are using and they seem OK to me.

    I hope this will help,

    Regards,

  • Hi,

    As i have to calculate inverse of sin to obtain AOA in radian, if i will be taking phase in radian then do i need to apply  inverse on radian(phase) to obtain AOA.

    Thanks 

    Akansha

  • Hi,

    I got it.

    Can yo please tell me how to utilize these angle values obtained from each IQ samples to get the AOA of that packet,

    Because i must get an AOA for one packet.

    So how to get actual AOA of a packet from these many angles obtained by IQ samples.

    Thanks and Regards

    Akansha

  • Hi,

    Generally speaking it is easier to do all the calculation using SI units (i.e. meter and radian).

    Regards,

  • Hi Akansha,

    Please note that you have to use the IQ samples coming from two different antennas to be able to get a phase difference and then be able to compute the AOA.

    BTW, please open a new thread dedicated to the problem you are facing with the python script when sampling the IQ data (this will be easier to follow up and clearer for the other readers).

    Thanks and regards,

  • Hi,

    Thanks for your suggestion for opening other thread.

    After knowing that IQ samples from two different antenna are required to calculate AOA, do you mean IQ samples from two different passive device?

    As IQ samples obtained from one passive only contain the data of antenna array from which they are sampled, there is no information regarding antenna of that array.

    Can you please elaborate on this query.

    Thanks

    Akansha

  • Hi,

    To calculate AOA you need to measure the phase difference between the CTE received by two antennas of the same antenna array (i.e. from the same passive device). This is explained in the introduction of the SLA lab.

    Knowing the sampling time on each antenna and the time required to switch from one antenna to the other (i.e. antenna switch settling time) you can know from which antenna a sample is coming from. As you are using the hardware provided by TI you can use the same values as the ones used in the embedded code. Please have a look to the SLA lab if you want to recalculate the antenna switch settling time.

    I hope this will help,