Other Parts Discussed in Thread: IWRL1432,
Steps for generating the compRangeBiasAndRxChanPhase line for the IWRL6432. Similar steps can be taken for the IWRL1432, just substitute 1432 for 6432 as appropriate.
1. Load the motion and presence demo found at C:\ti\MMWAVE_L_SDK_05_03_00_02\examples\mmw_demo\motion_and_presence_detection\prebuilt_binaries\xwrL64xx (or xwrl14xx for the IWRL1432 device).
2. Set a strong target like corner reflector at the distance of X meter (X less than 50 cm is not recommended) at boresight in a clutter-free environment. A large room or outdoors should be sufficient.
3. Add the following line to the configuration file intended for use. It is important to calibrate with a configuration file whose frequency range is similar to the range used in operation.
measureRangeBiasAndRxChanPhase 1 X D
The first argument "1" is to enable the measurement. The second argument, D, (in meters) is the distance of window around X where the peak will be searched. The purpose of the search window is to allow the test environment from not being overly constrained say because it may not be possible to clear it of all reflectors that may be stronger than the one used for calibration. The window size is recommended to be at least the distance equivalent of a few range bins.
4. Ensure that the configuration file fulfills the following constraints:
Constraint 1 | Major Motion must be enabled |
Third argument of sigProcChainCfg must be 1 or 3 sigProcChainCfg 32 2 3 0 0 0 0 15 |
Constraint 2 | Static Clutter Removal must be turned off | clutterRemoval 0 |
Constraint 3 | Phase Modulation Mode must be TDM, not BPM |
Fifth Argument of chirpComnCfg must be 1 chirpComnCfg 23 0 0 256 1 65.6 0 |
Constraint 4 |
Number of TX antennas must be 2 Number of RX antennas must be 3 |
channelCfg 7 3 0 |
An example of the changes needed can be found here in MotionDetectConfiguration.cfg
0066.MotionDetectCalibration.cfg
Use this version of the Industrial Visualizer to get output. Replace the python files in the Industrial Visualizer with those given below or just run the executable standalone.
Python Files :3630.gui_main.py
import struct import sys import serial import binascii import time import numpy as np import math import os import datetime # Local File Imports from parseTLVs import * from gui_common import * def parseStandardFrame(frameData): # Constants for parsing frame header headerStruct = 'Q8I' frameHeaderLen = struct.calcsize(headerStruct) tlvHeaderLength = 8 # Define the function's output structure and initialize error field to no error outputDict = {} outputDict['error'] = 0 # A sum to track the frame packet length for verification for transmission integrity totalLenCheck = 0 # Read in frame Header try: magic, version, totalPacketLen, platform, frameNum, timeCPUCycles, numDetectedObj, numTLVs, subFrameNum = struct.unpack(headerStruct, frameData[:frameHeaderLen]) except: print('Error: Could not read frame header') outputDict['error'] = 1 # Move frameData ptr to start of 1st TLV frameData = frameData[frameHeaderLen:] totalLenCheck += frameHeaderLen # Save frame number to output outputDict['frameNum'] = frameNum # Initialize the point cloud struct since it is modified by multiple TLV's # Each point has the following: X, Y, Z, Doppler, SNR, Noise, Track index outputDict['pointCloud'] = np.zeros((numDetectedObj, 7), np.float64) # Initialize the track indexes to a value which indicates no track outputDict['pointCloud'][:, 6] = 255 # Find and parse all TLV's for i in range(numTLVs): try: tlvType, tlvLength = tlvHeaderDecode(frameData[:tlvHeaderLength]) frameData = frameData[tlvHeaderLength:] totalLenCheck += tlvHeaderLength except: print('TLV Header Parsing Failure: Ignored frame due to parsing error') outputDict['error'] = 2 return {} # Detected Points if (tlvType == MMWDEMO_OUTPUT_MSG_DETECTED_POINTS): outputDict['numDetectedPoints'], outputDict['pointCloud'] = parsePointCloudTLV(frameData[:tlvLength], tlvLength, outputDict['pointCloud']) # Range Profile elif (tlvType == MMWDEMO_OUTPUT_MSG_RANGE_PROFILE): outputDict['rangeProfile'] = parseRangeProfileTLV(frameData[:tlvLength]) # Range Profile elif (tlvType == MMWDEMO_OUTPUT_EXT_MSG_RANGE_PROFILE_MAJOR): outputDict['rangeProfileMajor'] = parseRangeProfileTLV(frameData[:tlvLength]) # Range Profile elif (tlvType == MMWDEMO_OUTPUT_EXT_MSG_RANGE_PROFILE_MINOR): outputDict['rangeProfileMinor'] = parseRangeProfileTLV(frameData[:tlvLength]) # Noise Profile elif (tlvType == MMWDEMO_OUTPUT_MSG_NOISE_PROFILE): pass # Static Azimuth Heatmap elif (tlvType == MMWDEMO_OUTPUT_MSG_AZIMUT_STATIC_HEAT_MAP): pass # Range Doppler Heatmap elif (tlvType == MMWDEMO_OUTPUT_MSG_RANGE_DOPPLER_HEAT_MAP): pass # Performance Statistics elif (tlvType == MMWDEMO_OUTPUT_MSG_STATS): pass # Side Info elif (tlvType == MMWDEMO_OUTPUT_MSG_DETECTED_POINTS_SIDE_INFO): outputDict['pointCloud'] = parseSideInfoTLV(frameData[:tlvLength], tlvLength, outputDict['pointCloud']) # Azimuth Elevation Static Heatmap elif (tlvType == MMWDEMO_OUTPUT_MSG_AZIMUT_ELEVATION_STATIC_HEAT_MAP): pass # Temperature Statistics elif (tlvType == MMWDEMO_OUTPUT_MSG_TEMPERATURE_STATS): pass # Spherical Points elif (tlvType == MMWDEMO_OUTPUT_MSG_SPHERICAL_POINTS): outputDict['numDetectedPoints'], outputDict['pointCloud'] = parseSphericalPointCloudTLV(frameData[:tlvLength], tlvLength, outputDict['pointCloud']) # Target 3D elif (tlvType == MMWDEMO_OUTPUT_MSG_TRACKERPROC_3D_TARGET_LIST or tlvType == MMWDEMO_OUTPUT_EXT_MSG_TARGET_LIST): outputDict['numDetectedTracks'], outputDict['trackData'] = parseTrackTLV(frameData[:tlvLength], tlvLength) elif (tlvType == MMWDEMO_OUTPUT_MSG_TRACKERPROC_TARGET_HEIGHT): outputDict['numDetectedHeights'], outputDict['heightData'] = parseTrackHeightTLV(frameData[:tlvLength], tlvLength) # Target index elif (tlvType == MMWDEMO_OUTPUT_MSG_TRACKERPROC_TARGET_INDEX or tlvType == MMWDEMO_OUTPUT_EXT_MSG_TARGET_INDEX): outputDict['trackIndexes'] = parseTargetIndexTLV(frameData[:tlvLength], tlvLength) # Capon Compressed Spherical Coordinates elif (tlvType == MMWDEMO_OUTPUT_MSG_COMPRESSED_POINTS): outputDict['numDetectedPoints'], outputDict['pointCloud'] = parseCompressedSphericalPointCloudTLV(frameData[:tlvLength], tlvLength, outputDict['pointCloud']) # Presence Indication elif (tlvType == MMWDEMO_OUTPUT_MSG_PRESCENCE_INDICATION): pass # Occupancy State Machine elif (tlvType == MMWDEMO_OUTPUT_MSG_OCCUPANCY_STATE_MACHINE): outputDict['occupancy'] = parseOccStateMachTLV(frameData[:tlvLength]) elif (tlvType == MMWDEMO_OUTPUT_MSG_VITALSIGNS): outputDict['vitals'] = parseVitalSignsTLV(frameData[:tlvLength], tlvLength) elif(tlvType == MMWDEMO_OUTPUT_EXT_MSG_DETECTED_POINTS): outputDict['numDetectedPoints'], outputDict['pointCloud'] = parsePointCloudExtTLV(frameData[:tlvLength], tlvLength, outputDict['pointCloud']) elif (tlvType == MMWDEMO_OUTPUT_MSG_GESTURE_FEATURES_6843): outputDict['features'] = parseGestureFeaturesTLV(frameData[:tlvLength]) elif (tlvType == MMWDEMO_OUTPUT_MSG_GESTURE_OUTPUT_PROB_6843): outputDict['gestureNeuralNetProb'] = parseGestureProbTLV6843(frameData[:tlvLength]) elif (tlvType == MMWDEMO_OUTPUT_MSG_GESTURE_FEATURES_6432): # 6432 features output 350 outputDict['gestureFeatures'] = parseGestureFeaturesTLV6432(frameData[:tlvLength]) elif (tlvType == MMWDEMO_OUTPUT_MSG_GESTURE_CLASSIFIER_6432): outputDict['gesture'] = parseGestureClassifierTLV6432(frameData[:tlvLength]) elif (tlvType == MMWDEMO_OUTPUT_MSG_GESTURE_PRESENCE_x432): # outputDict['gesturePresence'] = parseGesturePresenceTLV6432(frameData[:tlvLength]) pass elif (tlvType == MMWDEMO_OUTPUT_MSG_GESTURE_PRESENCE_THRESH_x432): pass # Performance Statistics elif (tlvType == MMWDEMO_OUTPUT_MSG_EXT_STATS): outputDict['procTimeData'], outputDict['powerData'], outputDict['tempData'] \ = parseExtStatsTLV(frameData[:tlvLength], tlvLength) # Presence Detection in each zone elif(tlvType == MMWDEMO_OUTPUT_EXT_MSG_ENHANCED_PRESENCE_INDICATION): outputDict['enhancedPresenceDet'] = parseEnhancedPresenceInfoTLV(frameData[:tlvLength], tlvLength) # Probabilities output by the classifier elif(tlvType == MMWDEMO_OUTPUT_EXT_MSG_CLASSIFIER_INFO): outputDict['classifierOutput'] = parseClassifierTLV(frameData[:tlvLength], tlvLength) # Raw data from uDoppler extraction around targets elif(tlvType == MMWDEMO_OUTPUT_EXT_MSG_MICRO_DOPPLER_RAW_DATA): pass # uDoppler features from each target elif(tlvType == MMWDEMO_OUTPUT_EXT_MSG_MICRO_DOPPLER_FEATURES): pass # Surface classification value elif(tlvType == MMWDEMO_OUTPUT_MSG_SURFACE_CLASSIFICATION): outputDict['surfaceClassificationOutput'] = parseSurfaceClassificationTLV(frameData[:tlvLength]) elif(tlvType == MMWDEMO_OUTPUT_EXT_MSG_RX_CHAN_COMPENSATION_INFO): outputDict['rx_chan_comp'] = parseRXChanCompTLV(frameData[:tlvLength], tlvLength) else: print ("Warning: invalid TLV type: %d" % (tlvType)) # Move to next TLV frameData = frameData[tlvLength:] totalLenCheck += tlvLength # Pad totalLenCheck to the next largest multiple of 32 # since the device does this to the totalPacketLen for transmission uniformity totalLenCheck = 32 * math.ceil(totalLenCheck / 32) # Verify the total packet length to detect transmission error that will cause subsequent frames to dropped if (totalLenCheck != totalPacketLen): print('Warning: Frame packet length read is not equal to totalPacketLen in frame header. Subsequent frames may be dropped.') outputDict['error'] = 3 return outputDict # Decode TLV Header def tlvHeaderDecode(data): tlvType, tlvLength = struct.unpack('2I', data) return tlvType, tlvLength
import struct import sys import serial import binascii import time import numpy as np import math import os import datetime # Local File Imports from gui_common import * # ================================================== Common Helper Functions ================================================== # Convert 3D Spherical Points to Cartesian # Assumes sphericalPointCloud is an numpy array with at LEAST 3 dimensions # Order should be Range, Elevation, Azimuth def sphericalToCartesianPointCloud(sphericalPointCloud): shape = sphericalPointCloud.shape cartestianPointCloud = sphericalPointCloud.copy() if (shape[1] < 3): print('Error: Failed to convert spherical point cloud to cartesian due to numpy array with too few dimensions') return sphericalPointCloud # Compute X # Range * sin (azimuth) * cos (elevation) cartestianPointCloud[:,0] = sphericalPointCloud[:,0] * np.sin(sphericalPointCloud[:,1]) * np.cos(sphericalPointCloud[:,2]) # Compute Y # Range * cos (azimuth) * cos (elevation) cartestianPointCloud[:,1] = sphericalPointCloud[:,0] * np.cos(sphericalPointCloud[:,1]) * np.cos(sphericalPointCloud[:,2]) # Compute Z # Range * sin (elevation) cartestianPointCloud[:,2] = sphericalPointCloud[:,0] * np.sin(sphericalPointCloud[:,2]) return cartestianPointCloud # ================================================== Parsing Function For Individual TLV's ================================================== # Point Cloud TLV from SDK def parsePointCloudTLV(tlvData, tlvLength, pointCloud): pointStruct = '4f' # X, Y, Z, and Doppler pointStructSize = struct.calcsize(pointStruct) numPoints = int(tlvLength/pointStructSize) for i in range(numPoints): try: x, y, z, doppler = struct.unpack(pointStruct, tlvData[:pointStructSize]) except: numPoints = i print('Error: Point Cloud TLV Parser Failed') break tlvData = tlvData[pointStructSize:] pointCloud[i,0] = x pointCloud[i,1] = y pointCloud[i,2] = z pointCloud[i,3] = doppler return numPoints, pointCloud # Point Cloud Ext TLV from SDK for IWRL6432 def parsePointCloudExtTLV(tlvData, tlvLength, pointCloud): pUnitStruct = '4f2h' # Units for the 5 results to decompress them pointStruct = '4h2B' # x y z doppler snr noise pUnitSize = struct.calcsize(pUnitStruct) pointSize = struct.calcsize(pointStruct) # Parse the decompression factors try: pUnit = struct.unpack(pUnitStruct, tlvData[:pUnitSize]) except: print('Error: Point Cloud TLV Parser Failed') return 0, pointCloud # Update data pointer tlvData = tlvData[pUnitSize:] # Parse each point numPoints = int((tlvLength-pUnitSize)/pointSize) for i in range(numPoints): try: x, y, z, doppler, snr, noise = struct.unpack(pointStruct, tlvData[:pointSize]) except: numPoints = i print('Error: Point Cloud TLV Parser Failed') break tlvData = tlvData[pointSize:] # Decompress values pointCloud[i,0] = x * pUnit[0] # x pointCloud[i,1] = y * pUnit[0] # y pointCloud[i,2] = z * pUnit[0] # z pointCloud[i,3] = doppler * pUnit[1] # Dopper pointCloud[i,4] = snr * pUnit[2] # SNR pointCloud[i,5] = noise * pUnit[3] # Noise return numPoints, pointCloud # Enhanced Presence Detection TLV from SDK def parseEnhancedPresenceInfoTLV(tlvData, tlvLength): pointStruct = '1b' # While there are technically 2 bits per zone, we need to use at least 1 byte to represent pointStructSize = struct.calcsize(pointStruct) numZones = (tlvData[0]) # First byte in the TLV is the number of zones, the rest of it is the occupancy data zonePresence = [0] tlvData = tlvData[1:] zoneCount = 0 while(zoneCount < numZones): try: idx = math.floor((zoneCount)/4) zonePresence.append(tlvData[idx] >> (((zoneCount) * 2) % 8) & 3) zoneCount = zoneCount + 1 except: print('Error: Enhanced Presence Detection TLV Parser Failed') break tlvData = tlvData[pointStructSize:] return zonePresence # Side info TLV from SDK def parseSideInfoTLV(tlvData, tlvLength, pointCloud): pointStruct = '2H' # Two unsigned shorts: SNR and Noise pointStructSize = struct.calcsize(pointStruct) numPoints = int(tlvLength/pointStructSize) for i in range(numPoints): try: snr, noise = struct.unpack(pointStruct, tlvData[:pointStructSize]) except: numPoints = i print('Error: Side Info TLV Parser Failed') break tlvData = tlvData[pointStructSize:] # SNR and Noise are sent as uint16_t which are measured in 0.1 dB Steps pointCloud[i,4] = snr * 0.1 pointCloud[i,5] = noise * 0.1 return pointCloud # Range Profile Parser # MMWDEMO_OUTPUT_MSG_RANGE_PROFILE def parseRangeProfileTLV(tlvData): rangeProfile = [] rangeDataStruct = 'I' # Every range bin gets a uint32_t rangeDataSize = struct.calcsize(rangeDataStruct) numRangeBins = int(len(tlvData)/rangeDataSize) for i in range(numRangeBins): # Read in single range bin data try: rangeBinData = struct.unpack(rangeDataStruct, tlvData[:rangeDataSize]) except: print(f'Error: Range Profile TLV Parser Failed To Parse Range Bin Number ${i}') break rangeProfile.append(rangeBinData[0]) # Move to next value tlvData = tlvData[rangeDataSize:] return rangeProfile # Occupancy state machine TLV from small obstacle detection def parseOccStateMachTLV(tlvData): occStateMachOutput = [False] * 32 # Initialize to 32 empty zones occStateMachStruct = 'I' # Single uint32_t which holds 32 booleans occStateMachLength = struct.calcsize(occStateMachStruct) try: occStateMachData = struct.unpack(occStateMachStruct, tlvData[:occStateMachLength]) for i in range(32): # Since the occupied/not occupied flags are individual bits in a uint32, mask out each flag one at a time occStateMachOutput[i] = ((occStateMachData[0] & (1 << i)) != 0) except Exception as e: print('Error: Occupancy State Machine TLV Parser Failed') print(e) return None return occStateMachOutput # Spherical Point Cloud TLV Parser # MMWDEMO_OUTPUT_MSG_SPHERICAL_POINTS def parseSphericalPointCloudTLV(tlvData, tlvLength, pointCloud): pointStruct = '4f' # Range, Azimuth, Elevation, and Doppler pointStructSize = struct.calcsize(pointStruct) numPoints = int(tlvLength/pointStructSize) for i in range(numPoints): try: rng, azimuth, elevation, doppler = struct.unpack(pointStruct, tlvData[:pointStructSize]) except: numPoints = i print('Error: Point Cloud TLV Parser Failed') break tlvData = tlvData[pointStructSize:] pointCloud[i,0] = rng pointCloud[i,1] = azimuth pointCloud[i,2] = elevation pointCloud[i,3] = doppler # Convert from spherical to cartesian pointCloud[:,0:3] = sphericalToCartesianPointCloud(pointCloud[:, 0:3]) return numPoints, pointCloud # Point Cloud TLV from Capon Chain # MMWDEMO_OUTPUT_MSG_COMPRESSED_POINTS def parseCompressedSphericalPointCloudTLV(tlvData, tlvLength, pointCloud): pUnitStruct = '5f' # Units for the 5 results to decompress them pointStruct = '2bh2H' # Elevation, Azimuth, Doppler, Range, SNR pUnitSize = struct.calcsize(pUnitStruct) pointSize = struct.calcsize(pointStruct) # Parse the decompression factors try: pUnit = struct.unpack(pUnitStruct, tlvData[:pUnitSize]) except: print('Error: Point Cloud TLV Parser Failed') return 0, pointCloud # Update data pointer tlvData = tlvData[pUnitSize:] # Parse each point numPoints = int((tlvLength-pUnitSize)/pointSize) for i in range(numPoints): try: elevation, azimuth, doppler, rng, snr = struct.unpack(pointStruct, tlvData[:pointSize]) except: numPoints = i print('Error: Point Cloud TLV Parser Failed') break tlvData = tlvData[pointSize:] if (azimuth >= 128): print ('Az greater than 127') azimuth -= 256 if (elevation >= 128): print ('Elev greater than 127') elevation -= 256 if (doppler >= 32768): print ('Doppler greater than 32768') doppler -= 65536 # Decompress values pointCloud[i,0] = rng * pUnit[3] # Range pointCloud[i,1] = azimuth * pUnit[1] # Azimuth pointCloud[i,2] = elevation * pUnit[0] # Elevation pointCloud[i,3] = doppler * pUnit[2] # Doppler pointCloud[i,4] = snr * pUnit[4] # SNR # Convert from spherical to cartesian pointCloud[:,0:3] = sphericalToCartesianPointCloud(pointCloud[:, 0:3]) return numPoints, pointCloud # Decode 3D People Counting Target List TLV # MMWDEMO_OUTPUT_MSG_TRACKERPROC_3D_TARGET_LIST #3D Struct format #uint32_t tid; /*! @brief tracking ID */ #float posX; /*! @brief Detected target X coordinate, in m */ #float posY; /*! @brief Detected target Y coordinate, in m */ #float posZ; /*! @brief Detected target Z coordinate, in m */ #float velX; /*! @brief Detected target X velocity, in m/s */ #float velY; /*! @brief Detected target Y velocity, in m/s */ #float velZ; /*! @brief Detected target Z velocity, in m/s */ #float accX; /*! @brief Detected target X acceleration, in m/s2 */ #float accY; /*! @brief Detected target Y acceleration, in m/s2 */ #float accZ; /*! @brief Detected target Z acceleration, in m/s2 */ #float ec[16]; /*! @brief Target Error covarience matrix, [4x4 float], in row major order, range, azimuth, elev, doppler */ #float g; #float confidenceLevel; /*! @brief Tracker confidence metric*/ def parseTrackTLV(tlvData, tlvLength): targetStruct = 'I27f' targetSize = struct.calcsize(targetStruct) numDetectedTargets = int(tlvLength/targetSize) targets = np.empty((numDetectedTargets,16)) for i in range(numDetectedTargets): try: targetData = struct.unpack(targetStruct,tlvData[:targetSize]) except: print('ERROR: Target TLV parsing failed') return 0, targets targets[i,0] = targetData[0] # Target ID targets[i,1] = targetData[1] # X Position targets[i,2] = targetData[2] # Y Position targets[i,3] = targetData[3] # Z Position targets[i,4] = targetData[4] # X Velocity targets[i,5] = targetData[5] # Y Velocity targets[i,6] = targetData[6] # Z Velocity targets[i,7] = targetData[7] # X Acceleration targets[i,8] = targetData[8] # Y Acceleration targets[i,9] = targetData[9] # Z Acceleration targets[i,10] = targetData[26] # G targets[i,11] = targetData[27] # Confidence Level # Throw away EC tlvData = tlvData[targetSize:] return numDetectedTargets, targets def parseTrackHeightTLV(tlvData, tlvLength): targetStruct = 'I2f' #incoming data is an unsigned integer for TID, followed by 2 floats targetSize = struct.calcsize(targetStruct) numDetectedHeights = int(tlvLength/targetSize) heights = np.empty((numDetectedHeights,3)) for i in range(numDetectedHeights): try: targetData = struct.unpack(targetStruct,tlvData[i * targetSize:(i + 1) * targetSize]) except: print('ERROR: Target TLV parsing failed') return 0, heights heights[i,0] = targetData[0] # Target ID heights[i,1] = targetData[1] # maxZ heights[i,2] = targetData[2] # minZ return numDetectedHeights, heights # Decode Target Index TLV def parseTargetIndexTLV(tlvData, tlvLength): indexStruct = 'B' # One byte per index indexSize = struct.calcsize(indexStruct) numIndexes = int(tlvLength/indexSize) indexes = np.empty(numIndexes) for i in range(numIndexes): try: index = struct.unpack(indexStruct, tlvData[:indexSize]) except: print('ERROR: Target Index TLV Parsing Failed') return indexes indexes[i] = int(index[0]) tlvData = tlvData[indexSize:] return indexes def parseVitalSignsTLV (tlvData, tlvLength): vitalsStruct = '2H33f' vitalsSize = struct.calcsize(vitalsStruct) # Initialize struct in case of error vitalsOutput = {} vitalsOutput ['id'] = 999 vitalsOutput ['rangeBin'] = 0 vitalsOutput ['breathDeviation'] = 0 vitalsOutput ['heartRate'] = 0 vitalsOutput ['breathRate'] = 0 vitalsOutput ['heartWaveform'] = [] vitalsOutput ['breathWaveform'] = [] # Capture data for active patient try: vitalsData = struct.unpack(vitalsStruct, tlvData[:vitalsSize]) except: print('ERROR: Vitals TLV Parsing Failed') return vitalsOutput # Parse this patient's data vitalsOutput ['id'] = vitalsData[0] vitalsOutput ['rangeBin'] = vitalsData[1] vitalsOutput ['breathDeviation'] = vitalsData[2] vitalsOutput ['heartRate'] = vitalsData[3] vitalsOutput ['breathRate'] = vitalsData [4] vitalsOutput ['heartWaveform'] = np.asarray(vitalsData[5:20]) vitalsOutput ['breathWaveform'] = np.asarray(vitalsData[20:35]) # Advance tlv data pointer to end of this TLV tlvData = tlvData[vitalsSize:] return vitalsOutput def parseClassifierTLV(tlvData, tlvLength): classifierProbabilitiesStruct = str(NUM_CLASSES_IN_CLASSIFIER) + 'c' classifierProbabilitiesSize = struct.calcsize(classifierProbabilitiesStruct) numDetectedTargets = int(tlvLength/classifierProbabilitiesSize) outputProbabilities = np.empty((numDetectedTargets,NUM_CLASSES_IN_CLASSIFIER)) for i in range(numDetectedTargets): try: classifierProbabilities = struct.unpack(classifierProbabilitiesStruct,tlvData[:classifierProbabilitiesSize]) except: print('ERROR: Classifier TLV parsing failed') return 0, probabilities for j in range(NUM_CLASSES_IN_CLASSIFIER): outputProbabilities[i,j] = float(ord(classifierProbabilities[j])) / 128 # Throw away EC tlvData = tlvData[classifierProbabilitiesSize:] return outputProbabilities # Extracted features for 6843 Gesture Demo def parseGestureFeaturesTLV(tlvData): featuresStruct = '10f' featuresStructSize = struct.calcsize(featuresStruct) gesturefeatures = [] try: wtDoppler, wtDopplerPos, wtDopplerNeg, wtRange, numDetections, wtAzimuthMean, wtElevMean, azDoppCorr, wtAzimuthStd, wtdElevStd = struct.unpack(featuresStruct, tlvData[:featuresStructSize]) gesturefeatures = [wtDoppler, wtDopplerPos, wtDopplerNeg, wtRange, numDetections, wtAzimuthMean, wtElevMean, azDoppCorr, wtAzimuthStd, wtdElevStd] except: print('Error: Gesture Features TLV Parser Failed') return None return gesturefeatures # Raw ANN Probabilities TLV for 6843 Gesture Demo def parseGestureProbTLV6843(tlvData): probStruct = '10f' probStructSize = struct.calcsize(probStruct) try: annOutputProb = struct.unpack(probStruct, tlvData[:probStructSize]) except: print('Error: ANN Probabilities TLV Parser Failed') return None return annOutputProb # 6432 Gesture demo features def parseGestureFeaturesTLV6432(tlvData): featuresStruct = '16f' featuresStructSize = struct.calcsize(featuresStruct) gestureFeatures = [] try: gestureFeatures = struct.unpack(featuresStruct, tlvData[:featuresStructSize]) except: print('Error: Gesture Features TLV Parser Failed') return None return gestureFeatures # Detected gesture def parseGestureClassifierTLV6432(tlvData): classifierStruct = '1b' classifierStructSize = struct.calcsize(classifierStruct) classifier_result = 0 try: classifier_result = struct.unpack(classifierStruct, tlvData[:classifierStructSize]) except: print('Error: Classifier Result TLV Parser Failed') return None return classifier_result[0] # Surface Classification def parseSurfaceClassificationTLV(tlvData): classifierStruct = '1f' classifierStructSize = struct.calcsize(classifierStruct) classifier_result = 0 try: classifier_result = struct.unpack(classifierStruct, tlvData[:classifierStructSize]) except: print('Error: Classifier Result TLV Parser Failed') return None return classifier_result[0] # Mode in Gesture/KTO demo # def parseGesturePresenceTLV6432(tlvData): # presenceStruct = '1b' # presenceStructSize = struct.calcsize(presenceStruct) # presence_result = 0 # try: # presence_result = struct.unpack(presenceStruct, tlvData[:presenceStructSize]) # print(presence_result) # except: # print('Error: Gesture Presence Result TLV Parser Failed') # return None # return presence_result[0] def parseExtStatsTLV(tlvData, tlvLength): extStatsStruct = '2I8H' # Units for the 5 results to decompress them extStatsStructSize = struct.calcsize(extStatsStruct) # Parse the decompression factors try: interFrameProcTime, transmitOutTime, power1v8, power3v3, \ power1v2, power1v2RF, tempRx, tempTx, tempPM, tempDIG = \ struct.unpack(extStatsStruct, tlvData[:extStatsStructSize]) except: print('Error: Ext Stats Parser Failed') return 0 tlvData = tlvData[extStatsStructSize:] procTimeData = {} powerData = {} tempData = {} # print("IFPT : " + str(interFrameProcTime)) procTimeData['interFrameProcTime'] = interFrameProcTime procTimeData['transmitOutTime'] = transmitOutTime powerData['power1v8'] = power1v8 powerData['power3v3'] = power3v3 powerData['power1v2'] = power1v2 powerData['power1v2RF'] = power1v2RF tempData['tempRx'] = tempRx tempData['tempTx'] = tempTx tempData['tempPM'] = tempPM tempData['tempDIG'] = tempDIG return procTimeData, powerData, tempData def parseRXChanCompTLV(tlvData, tlvLength): compStruct = '13f' # One byte per index compSize = struct.calcsize(compStruct) coefficients = np.empty(compSize) try: coefficients = struct.unpack(compStruct, tlvData[:compSize]) except: print('ERROR: RX Channel Comp TLV Parsing Failed') # Print results to the terminal output print("compRangeBiasAndRxChanPhase", end=" ") for i in range(13): print(f'{coefficients[i]:0.4f}', end=" ") print('\n')
Executable : mmWave_Industrial_Visualizer_with_Calibration.exe