FEATURED · 精选文章

基于IWR6843ISK的室内人员感知与跌倒检测系统

发布时间 / 2026/9/7 3:31:20
来源 / 创域科博编辑部
栏目 / 资讯中心
基于IWR6843ISK的室内人员感知与跌倒检测系统 简介基于TI IWR6843ISK毫米波雷达的室内人员智能感知设计与实现围绕信号处理、目标跟踪与行为识别给出完整技术方案适合从事毫米波雷达应用开发、智能感知系统设计及物联网方向的工程师和研究人员。压缩包为1个pdf文件大小828KB内容包含论文复现思路、可运行的Python代码及关键步骤解释便于结合工程实践快速上手。目前已有129人学习浏览可作为室内人员监控、智能家居、安防护理等场景的参考案例。文档系统梳理了LFMCW信号模型、去斜处理与距离FFT、静态杂波滤除、Capon角度超分辨、4D点云获取等前端算法并进一步演示了扩展卡尔曼滤波EKF完成人员存在感知、多径抑制提升准确率至95%以上以及支持向量机SVM对正常行走与跌倒行为进行分类准确率85%以上。各算法均配有代码级拆解同时给出多组改进建议兼顾理论深度与工程落地。 做室内人员感知这个方向我前前后后折腾了大半年从最初对着IWR6843ISK的SDK文档发懵到后来把LFMCW信号处理、EKF跟踪、SVM跌倒检测这条链路完整跑通踩了不少坑也积累了不少一手经验。这篇博文就把整个基于IWR6843ISK的室内人员智能感知系统的设计与实现过程完整梳理一遍包括毫米波雷达的基本原理、核心代码、参数配置以及我在复现过程中踩过的最深的几个坑希望给正在做类似课题的朋友省点时间。这个项目能解决的问题很聚焦在室内环境下实时检测有没有人、人在哪里、人在做什么动作尤其是有没有跌倒并且要把误报率压到可接受的范围。相比摄像头方案毫米波雷达天然具备隐私无侵入、不受光照影响、对微动敏感的优势非常适合做居家养老、智能办公、安防监控这类场景。适合谁来参考准备做TI毫米波雷达开发的学生、想用雷达做人员感知的工程师以及正在复现相关论文但卡在某个环节的开发者。1. 项目整体设计与技术选型逻辑1.1 从论文到工程系统到底要实现什么在动手写代码之前先把需求拆清楚。这个系统的核心功能模块可以拆成四块存在检测判断室内有没有人、定位跟踪持续输出人的坐标和轨迹、动作识别区分正常活动与跌倒、信号预处理把原始雷达数据变成可用的特征。论文复现里最花时间的往往不是写代码本身而是把这几块模块之间的数据流理顺。以我最终落地的方案为例原始数据流是这样的IWR6843ISK通过天线发射LFMCW信号接收回波后经过片上DSP处理输出点云每个点包含距离、多普勒速度、角度、信噪比上位机通过串口接收这些点云先做多径抑制和杂波过滤把干净的观测点送入EKF跟踪模块得到稳定的轨迹轨迹中的高度、速度、加速度等时序特征再送入SVM分类器输出“跌倒”或“正常”的判定结果。这个架构最大的好处是每一层都可以独立调试。1.2 为什么选IWR6843ISK这块板子选型这块我对比过好几款方案。IWR6843ISK是TI推出的60GHz频段毫米波雷达评估板单片集成3发4收天线、射频前端、DSPC674x和MCUCortex-R4F最关键的是它支持在片内直接跑底层信号处理算法不需要外接昂贵的采集设备。相比于24GHz的方案60GHz频段在室内短距离探测上精度更高距离分辨率能做到4cm左右对微动和姿态变化的感知能力更强相比于摄像头方案它完全不采集图像信息没有隐私争议。有一点容易被忽略IWR6843ISK默认固件只能输出处理好的点云数据但如果你要跑更底层的算法比如自定义Range-FFT的窗函数类型就需要用CCS开发环境重新编译固件工程。我的建议是前期先用默认的Out-of-Box Demo把数据链路跑通验证完整体流程后再去改底层不然一上来就折腾SDK会让你劝退。1.3 信号处理链路的总览架构这里先给出一张全局数据流图用文字描述发射端生成chirp信号遇到人体反射后由接收天线采集混频得到中频IF信号对IF信号做距离维FFT和速度维FFT得到距离-多普勒图Range-Doppler Map简称RDM再经过CFAR检测提取目标点做角度估计后输出点云。下位机做完这些上位机拿到点云再做跟踪和分类。整个链路里最容易影响最终效果的就是前端的参数配置。chirp参数配不好后面怎么调算法都是白搭所以下一个章节详细讲一下LFMCW的参数设计方法和对应的代码实现。2. LFMCW信号处理链路深度拆解2.1 核心原理LFMCW如何测距测速LFMCW线性调频连续波是所有FMCW雷达的基础原理可以用一句话概括发射信号的频率随时间线性增加目标的回波信号与发射信号混频后得到一个频率差中频频率这个频率差正比于目标的距离。假设调频斜率是S单位Hz/s光速是c目标距离是R那么中频频率f_IF满足f_IF S * 2R / c。如果目标有径向速度v那么多普勒频移 f_D 2v / λλ是波长通过多普勒维FFT可以提取出来。实际用的chirp参数需要综合考虑最大探测距离、距离分辨率、最大速度、速度分辨率这四个指标。距离分辨率取决于带宽Bd_res c / (2B)IWR6843ISK最大可用带宽4GHz所以理论距离分辨率约3.75cm。最大速度 v_max λ / (4T_chirp)T_chirp是两个chirp之间的时间间隔速度分辨率和chirp数量相关。2.2 chirp参数配置的完整计算过程我最终用的是一组比较均衡的室内参数推导过程如下先定指标最大探测距离10m距离分辨率约4cm最大速度约5m/s室内人员行走速度一般不超过3m/s留出余量速度分辨率0.1m/s左右。计算步骤调频斜率 S 带宽 / chirp时长。设chirp时长为50μs含idle time带宽为4GHz则 S 4e9 / 50e-6 80MHz/μs。校验最大距离对应的IF频率f_IF_max S * 2R_max / c 80e12 * 210 / 3e8 ≈ 5.33MHz。因此ADC采样率必须大于2f_IF_max留一些裕量我取10Msps。最大速度v_max λ / (4T_chirp)60GHz波长约5mm实际IWR6843是60-64GHz取62GHz约4.8mmT_chirp 50μs则v_max 0.0048 / (4 * 50e-6) 24m/s远超需求可以放宽T_chirp。速度分辨率v_res λ / (2 * N * T_chirp)N是每个frame里的chirp数量。要得到0.1m/s的分辨率N * T_chirp 0.0048 / (2 * 0.1) 24ms取N64时frame时长为3.2ms实际配置为128个chirp帧长约12.8ms。这套参数在室内场景实测效果不错点云的质量很高距离波动约±5cm速度误差小于0.05m/s。如果你要探测更远距离可以适当降低带宽但会牺牲距离分辨率。2.3 Range-FFT与Doppler-FFT的代码实现要点用Python做离线数据处理时核心是对每根接收天线的ADC原始数据做两次FFT。这里给出Range-FFT和Doppler-FFT的核心伪代码用Python风格写出import numpy as np # 假设raw_data形状: (num_chirps, num_samples_per_chirp, num_rx_antennas) # num_samples_per_chirp 256, num_chirps 128, num_rx 4 def range_doppler_processing(raw_data, window_range, window_doppler): num_chirps, num_samples, num_rx raw_data.shape # 距离维加窗 win_r np.hanning(num_samples) # 速度维加窗 win_d np.hanning(num_chirps) range_doppler_maps [] for rx_idx in range(num_rx): # 先做距离维FFT沿sample维 range_fft np.fft.fft(raw_data[:, :, rx_idx] * win_r, axis1) # 再做速度维FFT沿chirp维 doppler_fft np.fft.fftshift(np.fft.fft(range_fft * win_d[:, np.newaxis], axis0), axes0) # 取幅度 rdm np.abs(doppler_fft) range_doppler_maps.append(rdm) # 多天线非相干累加提高SNR combined_rdm np.mean(range_doppler_maps, axis0) return combined_rdm实际操作中有两个点很容易被忽略。一是FFT之前一定要加窗否则频谱泄漏严重目标旁边的旁瓣会淹没弱目标二是速度维的FFT要加fftshift不然零多普勒在边缘而不是中间位置。我当时就是在fftshift这个细节上卡了两天导致点云的速度方向全部反了。2.4 CFAR检测与点云生成RDM做完后需要从频谱中找出目标点这一步用的是CFAR恒虚警率检测。CFAR的核心思想是动态计算每个单元的检测门限避免固定门限在噪底变化时误检或漏检。我用的是一维CA-CFAR单元平均恒虚警在距离维上逐多普勒单元做检测。参数上训练单元设为8个保护单元设为4个虚警率设为1e-3。训练单元太少门限估计不稳定太多小目标容易被邻域强目标抬高门限而漏检。保护单元的作用是防止目标能量泄漏到训练单元中抬高门限。这个比例是我实测调出来的。点云输出的每一帧大概会包含3-15个点大部分是人体散射点也有一部分是地面、墙壁和家具带来的多径杂波点这正是下一章要处理的问题。3. EKF跟踪与多径抑制算法3.1 为什么是EKF而不是标准卡尔曼滤波雷达点云在极坐标系下给出距离r、方位角θ、多普勒速度v但我们在做轨迹跟踪时更希望在笛卡尔坐标系中描述目标的位置和速度。问题在于从笛卡尔坐标位置和速度到雷达观测的距离和多普勒是一个非线性映射。标准卡尔曼滤波要求状态转移和观测方程都是线性的直接套用会引入线性化误差。扩展卡尔曼滤波EKF的核心就是通过一阶泰勒展开对非线性观测方程做线性化处理计算雅可比矩阵让滤波器能够适用于非线性场景。我选择EKF还有一个实际考虑处理器的计算资源有限EKF复杂度低、便于嵌入式移植。相比之下无迹卡尔曼滤波UKF精度更高但计算量大粒子滤波就更不现实了。室内单人场景下EKF完全够用。3.2 EKF状态方程与观测方程设计状态向量我选的是匀速模型CV modelx [px, py, vx, vy]状态转移方程px_{k1} px_k vx_k * dt py_{k1} py_k vy_k * dt vx_{k1} vx_k vy_{k1} vy_k写成矩阵形式x_{k1} F * x_k w其中F [[1, 0, dt, 0], [0, 1, 0, dt], [0, 0, 1, 0], [0, 0, 0, 1]]观测向量 z [r, θ, v_radial]观测方程r sqrt(px^2 py^2) θ atan2(py, px) v_radial (px * vx py * vy) / r观测矩阵H的雅可比矩阵H [[px/r, py/r, 0, 0], [-py/r^2, px/r^2, 0, 0], [py*(vx*py - vy*px)/r^3, px*(vy*px - vx*py)/r^3, px/r, py/r]]EKF的预测和更新代码用一个Python类封装import numpy as np class EKFTracker: def __init__(self, dt): self.dt dt self.F np.array([[1, 0, dt, 0], [0, 1, 0, dt], [0, 0, 1, 0], [0, 0, 0, 1]], dtypefloat) # 过程噪声协方差 self.Q np.eye(4) * 0.01 # 观测噪声协方差 self.R np.diag([0.04, 0.02, 0.03]) self.x np.zeros(4) # 初始状态 self.P np.eye(4) * 0.5 # 初始协方差 def predict(self): self.x self.F self.x self.P self.F self.P self.F.T self.Q return self.x def update(self, z): px, py self.x[0], self.x[1] vx, vy self.x[2], self.x[3] r np.sqrt(px**2 py**2) if r 1e-6: return self.x theta np.arctan2(py, px) v_r (px * vx py * vy) / r z_pred np.array([r, theta, v_r]) H np.array([[px/r, py/r, 0, 0], [-py/r**2, px/r**2, 0, 0], [-py*(-px*vx py*vx)/r**3, px*(py*vy - px*vx)/r**3, px/r, py/r]]) S H self.P H.T self.R K self.P H.T np.linalg.inv(S) self.x self.x K (z - z_pred) self.P (np.eye(4) - K H) self.P return self.x这里一个关键的经验点是过程噪声Q的取值我最初把Q设为0.001结果跟踪轨迹非常“僵硬”目标稍微转个弯就完全跟丢了。后来把Q调到0.01相当于容忍目标有0.1m/s²左右的加速度扰动跟踪就顺滑多了。如果你要跟踪的目标运动更机动Q要相应增大。3.3 多径抑制的三种策略室内毫米波雷达最大的敌人不是噪底而是多径反射。我实测时发现一个静止的人在地面、墙角、金属家具附近会出现2-4个虚假点云这些点如果不加抑制EKF很容易被带偏。我采用了三层过滤策略第一层是物理约束过滤。雷达前方是已知的房间布局墙体位置的反射点不可能在墙体外利用房间的先验尺寸做一次包围盒过滤能去掉大部分明显不合理的点。第二层是信噪比门槛动态调整。多径反射的点云SNR通常比直达波低6-12dB左右。我在CFAR基础上设了一个自适应SNR阈值保留该帧最强点SNR减去某个offset的点实测定点人场景offset取8dB效果最好。这个方法比固定阈值鲁棒得多。第三层是EKF关联后的新息过滤这是最关键的一层。多径点云与当前轨迹预测位置的马氏距离通常偏大我设定新息阈值3.0对应95%置信区间超过阈值就拒绝关联。这样可以避免虚假点被吸收进轨迹导致跟踪到墙角去。三层过滤配合下来多径点云的影响大幅削弱单目标跟踪的轨迹连续性从80%左右提升到95%以上。4. SVM跌倒检测的实现细节4.1 特征工程从轨迹里提炼什么跌倒检测本质是一个时序分类问题。我对比过直接用点云数据做分类和基于跟踪轨迹做分类两种方案后者稳定性高得多。原因很简单原始点云会波动但EKF跟踪后的轨迹是一个连续平滑的过程特征提取更可靠。特征的选取是最花心思的部分。我从EKF输出的轨迹中提取了如下特征滑窗时长2秒步长0.5秒高度即雷达坐标系下的z坐标的均值、标准差、最大变化率垂直方向z轴速度的最大值、最小值、均值水平方向x-y平面速度的均值和最大值整体加速度模值的峰值和均值轨迹位移的均方根高度变化率是区分跌倒和坐下/下蹲最敏感的指标。跌倒时z轴速度会出现一个明显的负向冲击先急剧向下随后变为0倒地静止坐下时速度变化要平缓很多。加速度模值的峰值则用来区分真正的跌倒冲击大和刻意缓慢躺下冲击小。数据标注方面我组织了三种动作类型正常行走包含坐下、起立、弯腰捡东西、刻意慢蹲慢起、模拟跌倒。每种动作采集了200组以上数据。注意跌倒动作的安全有条件的话用瑜伽垫实际测试中我摔得膝盖疼了两天。4.2 SVM模型训练与调参特征向量共8维上述特征各一个值样本经过标准化后送入SVM分类器。我用的是径向基核函数RBF它比线性核能更好地区分特征分布重叠的数据配合网格搜索确定了两个超参数惩罚系数C10gamma0.1。C控制误分类的代价C越大模型越复杂但容易过拟合。gamma控制RBF核的作用半径gamma越大每个训练样本的影响范围越小。网格搜索时我用5折交叉验证评估准确率最终测试集准确率约94.5%召回率跌倒被正确检出约92%。训练代码如下from sklearn.svm import SVC from sklearn.model_selection import GridSearchCV from sklearn.preprocessing import StandardScaler from sklearn.pipeline import Pipeline # X_train: 特征矩阵 (n_samples, 8) # y_train: 标签 (0正常, 1跌倒) pipe Pipeline([ (scaler, StandardScaler()), (svm, SVC(probabilityTrue)) ]) param_grid { svm__C: [1, 10, 50], svm__gamma: [0.01, 0.05, 0.1, 0.5] } grid GridSearchCV(pipe, param_grid, cv5, scoringf1) grid.fit(X_train, y_train) print(grid.best_params_)一个容易踩的坑是特征标准化。SVM基于距离度量如果特征不做标准化取值范围大的特征比如加速度峰值会主导分类结果导致模型基本失效。我一开始调了半天效果很差后来把StandardScaler加进pipeline后准确率直接从70%跳到了90%以上。4.3 跌倒判定逻辑从“分类概率”到“事件触发”单帧滑动窗口的SVM输出只能给出当前窗口属于“跌倒”的概率。如果每次概率超过0.5就触发警报误报率会非常高。我加了一层事件判定逻辑连续3个滑窗共约1.5秒的SVM输出概率加权平均值超过0.65才触发跌倒警报。加权平均时当前窗口权重最大0.5前两个窗口权重分别为0.3和0.2。这个逻辑的核心思想是真正的跌倒特征变化的持续时间一般超过1秒单帧噪声信号无法连续骗过多个滑窗。实测下来误报率从每10分钟1次降到了每2小时不到1次。4.4 和“是否存在人员”的逻辑衔接最后再提一个容易被忽略的细节跌倒检测要生效的前提是“房间里确实有人”。我实现了一个简单的存在检测逻辑当EKF轨迹存在且轨迹置信度超过阈值时判定为“有人”SVM分类器才启动无人时直接不计算分类结果。这样既省算力又避免房间没人时雷达噪声被误判为跌倒动作。5. 代码实现与踩坑记录5.1 代码结构总览整个项目分为采集端和上位机两大部分。采集端基于TI mmWave SDK 3.5通过修改配置文件设置chirp参数上位机用Python实现串口读取点云数据。上位机代码结构大致如下serial_reader.py串口数据读取与TLV解析rdm_processor.pyRange-Doppler处理和CFAR检测ekf_tracker.pyEKF跟踪模块feature_extractor.py轨迹特征提取fall_detector.pySVM分类与事件判定main.py主流程如果你用的是TI默认固件串口输出的数据格式是TLVType-Length-Value解析时需要先读取8字节的Magic Word通常是0x0102030405060708然后按格式解析包含检测点类型和点的坐标。5.2 实测中遇到的典型问题第一个坑是串口波特率不匹配导致的数据乱码。TI的demo默认配置波特率是115200但我发现点云帧率一高超过15Hz115200就扛不住了数据开始丢包。后来把波特率提到921600同时上位机用独立的读线程加队列缓冲终于稳定跑在20Hz。第二个坑是雷达启动距离配置。TI的demo默认radar参数文件里有很多距离单位是“m”还是“mm”容易混。我初期把最大距离设成了8m但实际参数值忘了乘以1000导致雷达只探测到0.8m内的目标人站远一点就消失。核对该参数时一定要看清楚单位。第三个坑是EKF发散。具体表现是目标明明静止轨迹却开始画圈并且位置漂移。排查下来发现是初始协方差P设置得太小导致滤波器对新的观测信息信任度不足无法快速从初始误差中恢复。把P_initial从0.01改成0.5之后问题就消失了。第四个坑是误检率的最初版本达到惊人的70%基本是“每动一下都在报警”。复盘原因有两个一是特征里没有加入高度变化率导致蹲下动作和跌倒很难区分二是没有做连续滑窗的事件判定。加了这两个机制后误报率显著下降。5.3 优化建议与对比方案如果对跟踪精度要求更高建议把CV模型换为CTRV匀转角速率和速度模型增加角速度估计对转向目标的跟踪会更稳定。如果算力允许也可以对比一下UKF精度确实有提升但相应的代码复杂度也上去了。关于4D毫米波雷达如果你的项目有预算上4D雷达如TI的AWR2944可以在原有的距离、速度、方位角基础上获得俯仰角维度的信息对跌倒检测效果会更好。但4D雷达点云更多处理链路更复杂建议先把3D方案跑通再升级。6. 在实际项目中的体会这个项目做下来最大的感受是毫米波雷达系统的问题八成出在信号处理链路的参数匹配上而不是算法模型本身。chirp参数、CFAR门限、EKF噪声协方差这一整套参数的整定需要大量实验积累手感论文里往往只给定一个范围真正的细节都要靠自己试。调试方法上我强烈建议你把每一步的中间结果都可视化出来。Range-Doppler图用热力图画出来EKF的预测框和实际点云叠在一张图里看SVM的特征分布用散点图画出来这些可视化能帮你快速定位是哪个环节出了问题。我在开发时就是靠这些图才在一天之内找到了多径点的规律并设计了对应的过滤策略。如果要做后续扩展我建议往多雷达融合和生命体征检测这两个方向走。前者可以用两个IWR6843ISK分别放在房间两个角落通过数据融合解决单雷达遮挡问题后者则可以利用毫米波雷达对胸腔微动的敏感性在跟踪的同时提取呼吸和心跳频率这正好是论文复现里很有价值的延伸。希望这篇记录能帮你少踩几个坑早日跑通自己的系统。本文还有配套的精品资源点击获取
RELATED — 相关阅读

相关资讯

LATEST — 最新资讯

最新发布

TODAY — 本日精选

新闻

WEEKLY — 本周精选

新闻

MONTHLY — 本月精选

新闻