TI毫米波雷达(四)—— out of box示例解析(三)
概述
分析命令行代码和配置文件之后发现分析了个寂寞,并没有揭开毫米波雷达目标检测的神秘面纱。或许是因为示例工程基于IWR1843,其HWA+DSP的架构允许将处理过程放到HWA中,自然就不会有很多关于处理过程的代码。那就再看看data path相关文档,看看其中有没有我要找的答案。
参考
《mmwave sdk uer guide》
《Radar Hardware Accelerator User's Guide》
《.../packages/tidemo/xwr18xx/mmw/docs/doxygen/html/index.html》
《.../packages/ti/datapath/dpc/objectdetection/objdethwa/docs/doxygen/html/index.html》
典型处理链路
典型的毫米波雷达处理链,它接受来自毫米波前端的ADC数据作为输入,然后执行距离和多普勒FFT,然后使用CFAR进行非相干检测。最后,使用3D FFT估计角度,检测到的点表示点云数据。然后,可以使用更高层的算法(如聚类、跟踪、分类)对点云数据进行后处理。

不同毫米波雷达型号包含不同的处理单元(HWA/DSP/HWA+DSP)来实现毫米波处理,对于具有HWA+DSP的设备(例如IWR1843),毫米波检测处理链可以根据性能和可扩展性的需要利用它们。下图显示了一个检测处理链的示例,该链使用各种数据处理单元(DPU)执行典型的毫米波处理,直至点云。毫米波设备存储器中的毫米波数据表示形成了各种DPU之间的接口层。每个DPU都可以使用HWA或DSP处理节点独立实现——选择取决于用例或给定毫米波设备上该处理节点的可用性。

Data Path
数据路径时序的顶层示意图如下:

如时序图所示,数据路径处理被分为两个周期:采集周期和帧间周期。
采集周期
啁啾期间的处理包括1D(距离)FFT处理,该处理从ADC缓冲器中的多个接收天线获取每个啁啾的输入,并对其执行FFT,并以DPIF_RADARCUBE_format_1定义的格式将输出生成到L3 RAM中。
帧间周期
啁啾结束到下一个啁啾开始的处理通常包含如下过程,这些
- 启用静态杂波去除后,将从场景中删除所有静态对象
- 2D(速度)FFT处理,从L3 RAM中的1D输出中获取输入,并执行FFT以在L3 RAM中给出(距离、速度)矩阵。
- CFAR处理和峰值分组对多普勒处理的检测矩阵输出。
- 到达角度(方位角、仰角)处理,以生成具有位置坐标(x、y、z)和速度的检测对象的最终列表。
应用中如何执行数据处理链
文档中直接向我们展示了APP-DPC的执行流程,我们对照着代码来看看。

DPM_init
dss_main.c中看到了DPM_init()函数 ,但仅能追踪到dpm.h文件中的一个声明。
DPC_ObjectDetection_init
这里发现了DPM_init()函数导致DPC中执行了DPC_ObjectDetection_init()。通过反推,才找到文件“objectdetection.c",在这个文件中实现了相关函数并赋值给结构体DPM_ProcChainCfg。
/**
* @brief Global used to register Object Detection DPC in DPM
*/
DPM_ProcChainCfg gDPC_ObjectDetectionCfg =
{
DPC_ObjectDetection_init, /* Initialization Function: */
DPC_ObjectDetection_start, /* Start Function: */
DPC_ObjectDetection_execute, /* Execute Function: */
DPC_ObjectDetection_ioctl, /* Configuration Function: */
DPC_ObjectDetection_stop, /* Stop Function: */
DPC_ObjectDetection_deinit, /* Deinitialization Function: */
NULL, /* Inject Data Function: */
NULL, /* Chirp Available Function: */
DPC_ObjectDetection_frameStart /* Frame Start Function: */
};
“objectdetection.h”中包含extern 声明并被“dss_main.c”引用,作为参数的一部分传递给了DPM_init()。
“objectdetection.h”
/*! Application developers: Use this configuration to load the Object Detection DPC
* within the DPM. */
extern DPM_ProcChainCfg gDPC_ObjectDetectionCfg;
"dss_main.c"
#include <ti/datapath/dpc/objectdetection/objdethwa/objectdetection.h>
/* Setup the configuration: */
dpmInitCfg.socHandle = gMmwDssMCB.socHandle;
dpmInitCfg.ptrProcChainCfg = &gDPC_ObjectDetectionCfg;
dpmInitCfg.instanceId = 0xFEEDFEED;
dpmInitCfg.domain = DPM_Domain_REMOTE;
dpmInitCfg.reportFxn = MmwDemo_DPC_ObjectDetection_reportFxn;
dpmInitCfg.arg = &objDetInitParams;
dpmInitCfg.argSize = sizeof(DPC_ObjectDetection_InitParams);
/* Initialize the DPM Module: */
gMmwDssMCB.dataPathObj.objDetDpmHandle = DPM_init (&dpmInitCfg, &errCode);
结构体DPM_ProcChainCfg在"dpm.h"中定义。
/**
* @brief
* Processing Chain Configuration
*
* @details
* The DPM module is responsible for the registeration and execution of
* processing chains. Processing Chains can be created and registered by
* populating the following configuration
*/
typedef struct DPM_ProcChainCfg_t
{
/**
* @brief Initialization function:
*/
DPM_ProcChainInitFxn initFxn;
/**
* @brief Start function:
*/
DPM_ProcChainStartFxn startFxn;
/**
* @brief Execute function:
*/
DPM_ProcChainExecuteFxn executeFxn;
/**
* @brief IOCTL function:
*/
DPM_ProcChainIoctlFxn ioctlFxn;
/**
* @brief Stop function:
*/
DPM_ProcChainStopFxn stopFxn;
/**
* @brief Deinitialization function:
*/
DPM_ProcChainDeinitFxn deinitFxn;
/**
* @brief [Optional] Inject Data Function:
*/
DPM_ProcChainInjectDataFxn injectDataFxn;
/**
* @brief [Optional] Chirp Available Callback function:
*/
DPM_ProcChainChirpAvailableCallbackFxn chirpAvailableFxn;
/**
* @brief [Optional] Frame Start Callback function:
*/
DPM_ProcChainFrameStartCallbackFxn frameStartFxn;
}DPM_ProcChainCfg;
这个API从堆中分配DPC实例和DPU实例(通过调用DPU的初始化API)。
DPU_RangeProcHWA_init()
DPU_StaticClutterProc_init()
DPU_CFARCAProcHWA_init()
DPU_DopplerProcHWA_init()
DPU_AoAProcHWA_init()
DPM_execute
此API在任务MmwDemo_DPC_ObjectDetection_dpmTask()中循环调用,其返回结果显示了有无检测目标。
DPM_ioctl
此API在"dpm.h"中声明,在“mss_main.c”中被如下函数调用。
- MmwDemo_DPM_ioctl_blocking()
- MmwDemo_handleObjectDetResult()
- MmwDemo_processPendingDynamicCfgCommands()
注意此函数在流程中多次调用并传递了不同参数:
- DPC_OBJDET_IOCTL__STATIC_PRE_START_COMMON_CFG
- DPC_OBJDET_IOCTL__STATIC_PRE_START_CFG
DPC_ObjectDetection_ioctl
此函数与DPC_ObjectDetection_init一同作为参数传递给DPM_init。可以通过DPM_ioctl传递的不同参数(包含子帧索引、预定于的配置等)在此函数中导致不同的配置。但示例中均使用了预启动配置。
通常如下函数可以被用来进行配置不同的数据处理单元:
- DPU_RangeProcHWA_config()
- DPU_StaticClutterProc_config()
- DPU_CFARCAProcHWA_config()
- DPU_DopplerProcHWA_config()
- DPU_AoAProcHWA_config()
ADCBuf配置
ADCBuf的配置通过命令行工具接收用户指令并执行。
DPM_start
DPM_start()在Demo中的调用过程如下:
- 用户通过命令行工具输入指令“sensorStart”,命令行工具调用MmwDemo_CLISensorStart()
- MmwDemo_CLISensorStart()中调用MmwDemo_startSensor()
- MmwDemo_startSensor()中调用MmwDemo_dataPathStart()
- MmwDemo_dataPathStart()中调用DPM_start()
DPC_ObjectDetection_start
此函数与DPC_ObjectDetection_init一同作为参数传递给DPM_init。此函数会触发距离数据处理单元DPU_RangeProcHWA_control()。
DPC_ObjectDetection_frameStart
此函数与DPC_ObjectDetection_init一同作为参数传递给DPM_init,DPC帧起始函数,调用DPM_notifyExecute()告知DPM模块DPC已就绪。
DPM_ioctl传递DPC_OBJDET_IOCTL__TRIGGER_FRAME参数以模拟触发,或RF前端接收到帧起始ISR时调用此函数。
DPC_ObjectDetection_execute
此函数与DPC_ObjectDetection_init一同作为参数传递给DPM_init,DPC帧数据处理函数。
当DPC_ObjectDetection_frameStart发出DPM_notifyExecute时,应用程序在DPM的执行上下文中调用该函数,该函数在每次帧中断时调用。
如下处理函数通常会被调用来处理数据:
- DPU_RangeProcHWA_process()
- DPU_StaticClutterProc_process()
- DPU_DopplerProcHWA_config()
- DPU_DopplerProcHWA_process()
- DPU_CFARCAProcHWA_config()
- DPU_CFARCAProcHWA_process()
- DPU_AoAProcHWA_config()
- DPU_AoAProcHWA_process()
总结
至此我们已经获得了足够的数据,后续就是数据的后处理,针对不同的应用场景和需求筛选出需要的目标了。
分析完命令行代码和数据路径之后,再看毫米波雷达的应用框图和SDK层级示意图就具体多了。虽然暂时还达不到一切细节了然于胸,但是继续前行的道路已经显现,只要后续不断学习深入,毫米波雷达程序开发肯定会越来越得心应手。


到目前为止仅仅是让毫米波雷达工作起来,满足了功能要求:检测到了目标,获取了目标的距离、速度、角度等数据。但是这些数据满足我们的性能要求吗?out of box示例和high accuracy的测距精度为什么不一样?看来还得研究研究神秘的啁啾(chirp)。
更多推荐
所有评论(0)