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.

CCS/IWR1443BOOST: How to send N bins of 1. FFT over UART into ROS?

Part Number: IWR1443BOOST
Other Parts Discussed in Thread: IWR1443, IWR6843AOP, DCA1000EVM

Tool/software: Code Composer Studio

Hi,

Task i'd like to see: Send 1. FFT n bins of all RX channels located in MmwDemo_DataPathObj::radarCube via UART to ROS.

My question:

How can 1. FFT data be selected from L3 (using MmwDemo_config2DSingleBin_EDMA?)

and sent out to ROS as "point Cloud" payload (using via MmwDemo_transmitProcessedOutput?) ?

 

Config is done by Demo Visualizer to limit data rate over UART < 1 Mbit/s and control duty cycle.

Startpoint is "out-of-the-box" demo.

Devices: IWR1443 ES3.0 and IWR6843AOP with specific SDK versions.

  • Uwe Wostradowski,

        UART would limit the bandwidth to < 1Mbit/s. 

    Have you reviewed the "TI mmWave ROS Driver User's Guide" in the below link? 

        http://dev.ti.com/tirex/explore/node?node=AOVWxEvg-HcESecamNaaLg__VLyFKFf__LATEST

    Thanks and regards,

    CHETHAN KUMAR Y.B.

  • Hi!

    thank you for quick response!

    UART would limit the bandwidth to < 1Mbit/s --> correct,

    therefore i'd like to reduce data to the only first n bins, e.g. 5 bins index 5 to 10.

    Yes,we checked out ROS Driver Guide,

    therefore we like to "change" payload from MmwDemo_transmitProcessedOutput to 1 .FFT [5..10] (index of 1. FFT bins)

    Please correct me: There is a considerable change in firmware needed? How?

    BR Uwe

  • Hi!

    thank you for quick response!

    UART would limit the bandwidth to < 1Mbit/s --> correct,

    therefore i'd like to reduce data to the only first n bins, e.g. 5 bins index 5 to 10.

    Yes,we checked out ROS Driver Guide,

    therefore we like to "change" payload from MmwDemo_transmitProcessedOutput to 1 .FFT [5..10] (index of 1. FFT bins)

    Please correct me: There is a considerable change in firmware needed? How?

    BR Uwe

  • Former Member
    0 Former Member in reply to Uwe Wostradowski

    Hello,

    Is it specifically that you want to receive the data within ROS or that you want the ability to capture the radar cube data into your PC environment?

    To avoid the UART limitation, you can use a DCA1000 and use the ethernet streaming to stream out the ADC data.

    If you are intent on modifying the OOB demo I would not start at the point cloud payload but rather one of the heatmaps.

    For example the Range-Azimuth heatmap - if you look at this data structure it is the 2D FFT array in range direction (rangebins x virtual antenna) at the 0 doppler index. 

    Amanda

  • Hi Amanda,

    actually we want to avoid DCA1000EVM and pick only the data to out radarCube that we want to have.

    We are using DCA1000EVM in offline mode, we see the data offline that we want.

    We also know, that DCA1000EVM can also used in streaming mode.

    But it is a mess with all these boards and cables knowing, that UART is fast enough for our applications

    We got perfect support on the config file, limiting FoV and reducing the data rate.

    But there are some steps like removing clutter and all the steps for detections, that delete our data, taht we want to have.

    In CCS we tried in main.c MmwDemo_transmitProcessedOutput to modifiy

    UART_writePolling (uartHandle,
                               (uint8_t*)&tl[tlvIdx],
                               sizeof(MmwDemo_output_message_tl));
    to
    UART_writePolling (uartHandle,
                               (uint8_t*)result->radarCube.data,
                               sizeof(result->radarCube.data));

    Build and Flash and load up the config --> radar sends out data, but it depands on numbe rof detection, the data stream changes between moving or static scene. This is not what we want, we want a fixed amount of 1. FFT bins of all 4 RX.

    We check out radarCube.format to be set correctly.

    --> Please give us a hint, if this way may work.

    BR Uwe

  • Former Member
    0 Former Member in reply to Uwe Wostradowski

    Hello,

    It's not clear which UART_writePolling you modified. If you modified the one for output of detected objects then you should also examine the if statement preceding it which only calls the write if there are detected objects.

    You can disable all the other write messages and just choose to write the header and the section of radar cube you are interested in for every frame.

    Can you provide the cfg and main file you are using - it may be easier to replicate your issue.

    Amanda

  • Former Member
    0 Former Member in reply to Former Member

    Hello Uwe,

    For a proof of concept here is the transmit function that I modified:

    Every frame the header is sent and the full radar cube. Note that I removed the padding and changed the numDetectedObjects to be the size of the radar cube.

    void MmwDemo_transmitProcessedOutput(UART_Handle uartHandle,
                                         DPC_ObjectDetection_ExecuteResult *result,
                                         MmwDemo_output_message_stats      *timingInfo)
    {
        MmwDemo_output_message_header header;
        MmwDemo_GuiMonSel   *pGuiMonSel;
        MmwDemo_SubFrameCfg *subFrameCfg;
        uint32_t tlvIdx = 0;
        uint32_t i;
        uint32_t numPaddingBytes;
        uint32_t packetLen;
        uint8_t padding[MMWDEMO_OUTPUT_MSG_SEGMENT_LEN];
        uint16_t *detMatrix = (uint16_t *)result->detMatrix.data;
    
        MmwDemo_output_message_tl   tl[MMWDEMO_OUTPUT_MSG_MAX];
    
        /* Get subframe configuration */
        subFrameCfg = &gMmwMCB.subFrameCfg[result->subFrameIdx];
    
        /* Get Gui Monitor configuration */
        pGuiMonSel = &subFrameCfg->guiMonSel;
    
        /* Clear message header */
        memset((void *)&header, 0, sizeof(MmwDemo_output_message_header));
        /* Header: */
        header.platform =  0xA6843;
        header.magicWord[0] = 0x0102;
        header.magicWord[1] = 0x0304;
        header.magicWord[2] = 0x0506;
        header.magicWord[3] = 0x0708;
        header.numDetectedObj = result->radarCube.dataSize;
        header.version =    MMWAVE_SDK_VERSION_BUILD |   //DEBUG_VERSION
                            (MMWAVE_SDK_VERSION_BUGFIX << 8) |
                            (MMWAVE_SDK_VERSION_MINOR << 16) |
                            (MMWAVE_SDK_VERSION_MAJOR << 24);
    
        packetLen = sizeof(MmwDemo_output_message_header)+result->radarCube.dataSize;
        /*if ((pGuiMonSel->detectedObjects == 1) || (pGuiMonSel->detectedObjects == 2) &&
             (result->numObjOut > 0))
        {
            tl[tlvIdx].type = MMWDEMO_OUTPUT_MSG_DETECTED_POINTS;
            tl[tlvIdx].length = sizeof(DPIF_PointCloudCartesian) * result->numObjOut;
            packetLen += sizeof(MmwDemo_output_message_tl) + tl[tlvIdx].length;
            tlvIdx++;
        }
         Side info
        if ((pGuiMonSel->detectedObjects == 1) && (result->numObjOut > 0))
        {
            tl[tlvIdx].type = MMWDEMO_OUTPUT_MSG_DETECTED_POINTS_SIDE_INFO;
            tl[tlvIdx].length = sizeof(DPIF_PointCloudSideInfo) * result->numObjOut;
            packetLen += sizeof(MmwDemo_output_message_tl) + tl[tlvIdx].length;
            tlvIdx++;
        }
        if (pGuiMonSel->logMagRange)
        {
            tl[tlvIdx].type = MMWDEMO_OUTPUT_MSG_RANGE_PROFILE;
            tl[tlvIdx].length = sizeof(uint16_t) * subFrameCfg->numRangeBins;
            packetLen += sizeof(MmwDemo_output_message_tl) + tl[tlvIdx].length;
            tlvIdx++;
        }
        if (pGuiMonSel->noiseProfile)
        {
            tl[tlvIdx].type = MMWDEMO_OUTPUT_MSG_NOISE_PROFILE;
            tl[tlvIdx].length = sizeof(uint16_t) * subFrameCfg->numRangeBins;
            packetLen += sizeof(MmwDemo_output_message_tl) + tl[tlvIdx].length;
            tlvIdx++;
        }
        if (pGuiMonSel->rangeAzimuthHeatMap)
        {
    #if defined(USE_2D_AOA_DPU)
            tl[tlvIdx].type = MMWDEMO_OUTPUT_MSG_AZIMUT_ELEVATION_STATIC_HEAT_MAP;
    #else
            tl[tlvIdx].type = MMWDEMO_OUTPUT_MSG_AZIMUT_STATIC_HEAT_MAP;
    #endif
            tl[tlvIdx].length = result->azimuthStaticHeatMapSize * sizeof(cmplx16ImRe_t);
            packetLen += sizeof(MmwDemo_output_message_tl) +  tl[tlvIdx].length;
            tlvIdx++;
        }
        if (pGuiMonSel->rangeDopplerHeatMap)
        {
            tl[tlvIdx].type = MMWDEMO_OUTPUT_MSG_RANGE_DOPPLER_HEAT_MAP;
            tl[tlvIdx].length = subFrameCfg->numRangeBins * subFrameCfg->numDopplerBins * sizeof(uint16_t);
            packetLen += sizeof(MmwDemo_output_message_tl) + tl[tlvIdx].length;
            tlvIdx++;
        }
        if (pGuiMonSel->statsInfo)
        {
            tl[tlvIdx].type = MMWDEMO_OUTPUT_MSG_STATS;
            tl[tlvIdx].length = sizeof(MmwDemo_output_message_stats);
            packetLen += sizeof(MmwDemo_output_message_tl) + tl[tlvIdx].length;
            tlvIdx++;
        } */
    
    
        /* Fill header */
        header.numTLVs = tlvIdx;
        /* Round up packet length to multiple of MMWDEMO_OUTPUT_MSG_SEGMENT_LEN */
        header.totalPacketLen = packetLen; // MMWDEMO_OUTPUT_MSG_SEGMENT_LEN * ((packetLen + (MMWDEMO_OUTPUT_MSG_SEGMENT_LEN-1))/MMWDEMO_OUTPUT_MSG_SEGMENT_LEN);
        header.timeCpuCycles =  Pmu_getCount(0);
        header.frameNumber = result->stats->frameStartIntCounter;
        header.subFrameNumber = result->subFrameIdx;
    
        UART_writePolling (uartHandle,
                           (uint8_t*)&header,
                           sizeof(MmwDemo_output_message_header));
    
        UART_writePolling (uartHandle,
                                   (uint8_t*)result->radarCube.data,
                                   result->radarCube.dataSize);
    
       /* tlvIdx = 0;
         Send detected Objects
        if ((pGuiMonSel->detectedObjects == 1) || (pGuiMonSel->detectedObjects == 2) &&
            (result->numObjOut > 0))
        {
            UART_writePolling (uartHandle,
                               (uint8_t*)&tl[tlvIdx],
                               sizeof(MmwDemo_output_message_tl));
    
            Send array of objects
            UART_writePolling (uartHandle, (uint8_t*)result->objOut,
                               sizeof(DPIF_PointCloudCartesian) * result->numObjOut);
            tlvIdx++;
        }
    
         Send detected Objects Side Info
        if ((pGuiMonSel->detectedObjects == 1) && (result->numObjOut > 0))
        {
            UART_writePolling (uartHandle,
                               (uint8_t*)&tl[tlvIdx],
                               sizeof(MmwDemo_output_message_tl));
    
            Send array of objects
            UART_writePolling (uartHandle, (uint8_t*)result->objOutSideInfo,
                               sizeof(DPIF_PointCloudSideInfo) * result->numObjOut);
            tlvIdx++;
        }
    
         Send Range profile
        if (pGuiMonSel->logMagRange)
        {
            UART_writePolling (uartHandle,
                               (uint8_t*)&tl[tlvIdx],
                               sizeof(MmwDemo_output_message_tl));
    
            for(i = 0; i < subFrameCfg->numRangeBins; i++)
            {
                UART_writePolling (uartHandle,
                        (uint8_t*)&detMatrix[i * subFrameCfg->numDopplerBins],
                        sizeof(uint16_t));
            }
            tlvIdx++;
        }
    
         Send noise profile
        if (pGuiMonSel->noiseProfile)
        {
            uint32_t maxDopIdx = subFrameCfg->numDopplerBins/2 -1;
            UART_writePolling (uartHandle,
                               (uint8_t*)&tl[tlvIdx],
                               sizeof(MmwDemo_output_message_tl));
    
            for(i = 0; i < subFrameCfg->numRangeBins; i++)
            {
                UART_writePolling (uartHandle,
                        (uint8_t*)&detMatrix[i * subFrameCfg->numDopplerBins + maxDopIdx],
                        sizeof(uint16_t));
            }
            tlvIdx++;
        }
    
         Send data for static azimuth heatmap
        if (pGuiMonSel->rangeAzimuthHeatMap)
        {
            UART_writePolling (uartHandle,
                               (uint8_t*)&tl[tlvIdx],
                               sizeof(MmwDemo_output_message_tl));
    
            UART_writePolling (uartHandle,
                    (uint8_t *) result->azimuthStaticHeatMap,
                    result->azimuthStaticHeatMapSize * sizeof(cmplx16ImRe_t));
    
            tlvIdx++;
        }
    
         Send data for range/Doppler heatmap
        if (pGuiMonSel->rangeDopplerHeatMap == 1)
        {
            UART_writePolling (uartHandle,
                               (uint8_t*)&tl[tlvIdx],
                               sizeof(MmwDemo_output_message_tl));
            UART_writePolling (uartHandle,
                    (uint8_t*)detMatrix,
                    tl[tlvIdx].length);
            tlvIdx++;
        }
    
         Send stats information
        if (pGuiMonSel->statsInfo == 1)
        {
            UART_writePolling (uartHandle,
                               (uint8_t*)&tl[tlvIdx],
                               sizeof(MmwDemo_output_message_tl));
            UART_writePolling (uartHandle,
                               (uint8_t*)timingInfo,
                               tl[tlvIdx].length);
            tlvIdx++;
        }
    */
        /* Send padding bytes */
    /*    numPaddingBytes = MMWDEMO_OUTPUT_MSG_SEGMENT_LEN - (packetLen & (MMWDEMO_OUTPUT_MSG_SEGMENT_LEN-1));
        if (numPaddingBytes<MMWDEMO_OUTPUT_MSG_SEGMENT_LEN)
        {
            UART_writePolling (uartHandle,
                                (uint8_t*)padding,
                                numPaddingBytes);
        }*/
    }

    Here is the cfg file I used to test on IWR6843AOP. Note that I intentionally tested an easy use case only 1TXx4RX with only 16 doppler bins and 128 range bin at 1fps. I only verified that the expected number of bytes for the radar cube appeared in the saved dat file. Using this cfg each frame should have 40bytes for the header + 32768 for the radar cube. I didn't verify the actual data itself.

    /cfs-file/__key/communityserver-discussions-components-files/1023/6765.profile-_2800_4_2900_.cfg

    Amanda

  • I can confirm the test!

    Thank you very much!

    Next step is now to put the data into ROS for further processing.