UWB定位的两种解法

news/2024/11/16 11:41:52/

UWB(Ultra-Wideband)技术是一种短脉冲无线电技术(短脉冲意味着信号的带宽很大,因此称为超宽带),其应用非常广泛,其中之一就是室内定位,通过计算信号传播的时间差,可以得到标签和基站之间的距离,如果有足够多的基站,就可以通过三角定位等方法计算出标签的位置。如下图所示:

在这里插入图片描述

本文将介绍两种利用标签与基站的距离信息求解标签位置的方法,分别是线性最小二乘和非线性优化。

线性最小二乘

对于线性最小二乘方法,假设有 m m m个基站,第 i i i个基站的坐标为 a i = ( a i , 1 , a i , 2 , a i , 3 ) a_i=(a_{i,1},a_{i,2},a_{i,3}) ai=(ai,1,ai,2,ai,3),标签与第 i i i个基站之间的距离为 r i r_i ri,标签的坐标为 x = ( x 1 , x 2 , x 3 ) x=(x_1,x_2,x_3) x=(x1,x2,x3)。则可以得到以下方程组:

{ ( x 1 − a 1 , 1 ) 2 + ( x 2 − a 1 , 2 ) 2 + ( x 3 − a 1 , 3 ) 2 = r 1 2 ( x 1 − a 2 , 1 ) 2 + ( x 2 − a 2 , 2 ) 2 + ( x 3 − a 2 , 3 ) 2 = r 2 2 ⋯ ( x 1 − a m , 1 ) 2 + ( x 2 − a m , 2 ) 2 + ( x 3 − a m , 3 ) 2 = r m 2 \begin{cases} (x_1-a_{1,1})^2+(x_2-a_{1,2})^2+(x_3-a_{1,3})^2=r_1^2 \\ (x_1-a_{2,1})^2+(x_2-a_{2,2})^2+(x_3-a_{2,3})^2=r_2^2 \\ \cdots \\ (x_1-a_{m,1})^2+(x_2-a_{m,2})^2+(x_3-a_{m,3})^2=r_m^2 \end{cases} (x1a1,1)2+(x2a1,2)2+(x3a1,3)2=r12(x1a2,1)2+(x2a2,2)2+(x3a2,3)2=r22(x1am,1)2+(x2am,2)2+(x3am,3)2=rm2

使用 a i a_i ai表示第 i i i个基站的坐标向量,向量的模表示为:

∣ ∣ a i ∣ ∣ = a i , 1 2 + a i , 2 2 + a i , 3 2 ||a_i||=\sqrt{a_{i,1}^2+a_{i,2}^2+a_{i,3}^2} ∣∣ai∣∣=ai,12+ai,22+ai,32

将第二行以及之后的方程减去第一行,可以得到以下方程组:

{ 2 ( a 1 − a 2 ) T x = r 2 2 − r 2 2 − ∣ ∣ a 2 ∣ ∣ 2 + ∣ ∣ a 1 ∣ ∣ 2 2 ( a 1 − a 3 ) T x = r 3 2 − r 1 2 − ∣ ∣ a 3 ∣ ∣ 2 + ∣ ∣ a 1 ∣ ∣ 2 ⋯ 2 ( a 1 − a m ) T x = r m 2 − r 1 2 − ∣ ∣ a m ∣ ∣ 2 + ∣ ∣ a 1 ∣ ∣ 2 \begin{cases} 2(a_1-a_2)^Tx=r_2^2 - r_2^2 - ||a_2||^2 + ||a_1||^2 \\ 2(a_1-a_3)^Tx=r_3^2 - r_1^2 - ||a_3||^2 + ||a_1||^2 \\ \cdots \\ 2(a_1-a_m)^Tx=r_m^2 - r_1^2 - ||a_m||^2 + ||a_1||^2 \end{cases} 2(a1a2)Tx=r22r22∣∣a22+∣∣a122(a1a3)Tx=r32r12∣∣a32+∣∣a122(a1am)Tx=rm2r12∣∣am2+∣∣a12

将上述方程组写成矩阵形式,可以得到:

[ 2 ( a 1 − a 2 ) T 2 ( a 1 − a 3 ) T ⋮ 2 ( a 1 − a m ) T ] x = [ r 2 2 − r 2 2 − ∣ ∣ a 2 ∣ ∣ 2 + ∣ ∣ a 1 ∣ ∣ 2 r 3 2 − r 1 2 − ∣ ∣ a 3 ∣ ∣ 2 + ∣ ∣ a 1 ∣ ∣ 2 ⋮ r m 2 − r 1 2 − ∣ ∣ a m ∣ ∣ 2 + ∣ ∣ a 1 ∣ ∣ 2 ] \begin{bmatrix} 2(a_1-a_2)^T \\ 2(a_1-a_3)^T \\ \vdots \\ 2(a_1-a_m)^T \end{bmatrix}x= \begin{bmatrix} r_2^2 - r_2^2 - ||a_2||^2 + ||a_1||^2 \\ r_3^2 - r_1^2 - ||a_3||^2 + ||a_1||^2 \\ \vdots \\ r_m^2 - r_1^2 - ||a_m||^2 + ||a_1||^2 \end{bmatrix} 2(a1a2)T2(a1a3)T2(a1am)T x= r22r22∣∣a22+∣∣a12r32r12∣∣a32+∣∣a12rm2r12∣∣am2+∣∣a12

A A A为上述矩阵, b b b为上述向量,则可以得到以下方程:

A x = b Ax=b Ax=b

使用矩阵的伪逆求解上述方程,即可得到标签的位置 x x x

非线性优化

非线性优化方法通过最小化标签与基站之间距离的误差来求解标签的位置,优化变量即为标签的位置。

具体来说,假设有 m m m个基站,第 i i i个基站的坐标为 a i = ( a i , 1 , a i , 2 , a i , 3 ) a_i=(a_{i,1},a_{i,2},a_{i,3}) ai=(ai,1,ai,2,ai,3),标签与第 i i i个基站之间的距离为 r i r_i ri,标签的坐标为 x = ( x 1 , x 2 , x 3 ) x=(x_1,x_2,x_3) x=(x1,x2,x3),则标签与第 i i i个基站之间距离的误差为:

f i ( x ) = ( x 1 − a i , 1 ) 2 + ( x 2 − a i , 2 ) 2 + ( x 3 − a i , 3 ) 2 − r i f_i(x)=\sqrt{(x_1-a_{i,1})^2+(x_2-a_{i,2})^2+(x_3-a_{i,3})^2}-r_i fi(x)=(x1ai,1)2+(x2ai,2)2+(x3ai,3)2 ri

将所有基站的误差平方和作为目标函数,即:

min ⁡ x ∑ i = 1 m f i 2 ( x ) \min_{x} \sum_{i=1}^{m} f_i^2(x) xmini=1mfi2(x)

该目标函数是一个非线性函数,可以使用非线性最小二乘法进行求解。具体来说,可以使用LM算法(Levenberg-Marquardt算法)对目标函数进行优化,求解出标签的位置 x x x

LM算法

LM算法是一种非线性最小二乘法的优化算法,可以用于求解非线性优化问题。它是一种介于Gauss-Newton算法和梯度下降算法之间的方法,具有收敛速度快、收敛性好等优点。

LM算法的流程如下:

  1. 初始化参数 x x x,设置初始步长 λ \lambda λ,设置容差 ϵ \epsilon ϵ,设置最大迭代次数 m a x _ i t e r max\_iter max_iter
  2. 计算误差向量 f ( x ) f(x) f(x)和雅可比矩阵 J ( x ) J(x) J(x)
  3. 计算增量 Δ x \Delta x Δx,其中 Δ x \Delta x Δx满足以下方程:

( J T J + λ I ) Δ x = − J T f ( x ) (J^TJ+\lambda I)\Delta x=-J^Tf(x) (JTJ+λI)Δx=JTf(x)

  1. 计算新的参数 x n e w = x + Δ x x_{new}=x+\Delta x xnew=x+Δx,计算新的误差向量 f ( x n e w ) f(x_{new}) f(xnew)
  2. 如果新的误差向量的平方和小于容差 ϵ \epsilon ϵ,则停止迭代;否则,判断新的误差向量是否比原来的误差向量更小,如果更小,则减小步长 λ \lambda λ,重复步骤2-5;否则,增加步长 λ \lambda λ,重复步骤2-5。

附录中给出了LM算法的C++实现,其中雅可比矩阵的计算使用了数值微分,也可以使用解析求导的方法进行计算:

∂ f i ∂ x j = x j − a i , j ( x 1 − a i , 1 ) 2 + ( x 2 − a i , 2 ) 2 + ( x 3 − a i , 3 ) 2 \frac{\partial f_i}{\partial x_j}=\frac{x_j-a_{i,j}}{\sqrt{(x_1-a_{i,1})^2+(x_2-a_{i,2})^2+(x_3-a_{i,3})^2}} xjfi=(x1ai,1)2+(x2ai,2)2+(x3ai,3)2 xjai,j

其中 j j j x x x的第 j j j个分量,分母表示标签与第 i i i个基站之间的距离。

附录:C++实现

本文代码基于Eigen库实现,包含的头文件如下:

#include <Eigen/Core>
#include <Eigen/Dense>

线性最小二乘

以下代码使用线性最小二乘法求解标签的位置,它是一个lambda表达式,输入参数为基站的坐标向量和标签与基站之间的距离,输出为标签的位置。

auto trilateration = [](const std::vector<Eigen::Vector3d>& uwb_stations, const std::vector<double>& uwb_range) {Eigen::MatrixXd A(uwb_stations.size() - 1, 3);Eigen::VectorXd b(uwb_stations.size() - 1);for (int i = 1; i < uwb_stations.size(); i++) {A.row(i - 1) = 2 * (uwb_stations[0] - uwb_stations[i]).transpose();b(i - 1) = uwb_range[i] * uwb_range[i] - uwb_range[0] * uwb_range[0] - (uwb_stations[i].squaredNorm() - uwb_stations[0].squaredNorm());}// 使用SVD求解线性最小二乘问题Eigen::Vector3d pos = A.jacobiSvd(Eigen::ComputeThinU | Eigen::ComputeThinV).solve(b);return std::vector<double>({pos[0], pos[1], pos[2]});
};

非线性优化

以下代码使用LM算法对上述目标函数进行优化,求解出标签的位置,求导过程使用了数值微分。

// 定义非线性优化问题
struct UWBProblem {// 测量值std::vector<double> ranges;// anchor坐标std::vector<std::vector<double>> anchors;// 优化变量std::vector<double> x;// 重载()运算符,计算误差int operator()(const double* x, double* fvec) const {for (int i = 0; i < ranges.size(); ++i) {double r = ranges[i];std::vector<double> a = anchors[i];double dist = sqrt(pow(x[0] - a[0], 2) + pow(x[1] - a[1], 2) + pow(x[2] - a[2], 2));fvec[i] = dist - r;}return 0;}
};// 非线性最小二乘法求解器
void levenbergMarquardt(UWBProblem& problem, double lambda, double tol, int max_iter) {Eigen::VectorXd x = Eigen::Map<Eigen::VectorXd>(problem.x.data(), problem.x.size());int n = x.size();int m = problem.ranges.size();Eigen::VectorXd fvec(m);Eigen::MatrixXd J(m, n);for (int iter = 0; iter < max_iter; ++iter) {// 计算误差向量和雅可比矩阵problem(x.data(), fvec.data());for (int i = 0; i < m; ++i) {for (int j = 0; j < n; ++j) {double h = 1e-6;Eigen::VectorXd x1 = x;x1(j) += h;Eigen::VectorXd fvec1(m);problem(x1.data(), fvec1.data());J(i, j) = (fvec1(i) - fvec(i)) / h;}}// 计算增量Eigen::MatrixXd JtJ = J.transpose() * J;Eigen::VectorXd Jtf = J.transpose() * fvec;JtJ.diagonal().array() += lambda;Eigen::VectorXd dx = -JtJ.ldlt().solve(Jtf);// 更新变量Eigen::VectorXd x_new = x + dx;// 判断是否收敛double err = fvec.squaredNorm();if (err < tol) {break;}// 更新lambdaEigen::VectorXd fvec_new(m);problem(x_new.data(), fvec_new.data());double err_new = fvec_new.squaredNorm();if (err_new < err) {lambda /= 10;x = x_new;fvec = fvec_new;} else {lambda *= 10;}}// 更新优化变量problem.x = std::vector<double>(x.data(), x.data() + x.size());
}

调用方法如下:

// 设置初始值
vector<double> x0 = {0, 0, 0};
// 设置测量值
std::vector<double> ranges;
// 设置anchor坐标
std::vector<std::vector<double>> anchors;
UWBProblem problem;
problem.ranges = ranges;
problem.anchors = anchors;
problem.x = x0;
// 进行优化
double lambda = 0.1;
double tol = 1e-6;
int max_iter = 1000;
levenbergMarquardt(problem, lambda, tol, max_iter);
// 输出优化结果
std::cout << "x = " << problem.x[0] << ", y = " << problem.x[1] << ", z = " << problem.x[2] << std::endl;

http://www.ppmy.cn/news/470593.html

相关文章

无法安装打印机驱动或者扫描仪驱动

安装驱动失败&#xff0c;尝试使用驱动精灵修复相关的系统驱动&#xff0c;修复后顺利安装打印驱动

扫描机驱动备份

扫描机型号驱动下载地址KODAK i2400&#xff0c;i2420&#xff0c;i2600&#xff0c;i2620https://resources.kodakalaris.com/docimaging/drivers/i2000March2018/InstallSoftware_i2000_v5.1.exeKODAK ScanMate i1150https://resources.kodakalaris.com/docimaging/drivers/i…

扫描器s-scan下载安装功能应用

扫描器&#xff0c;s-scan 配置&#xff0c;扫描网段&#xff0c;扫描什么&#xff0c;扫描原理&#xff0c;扫描地址&#xff0c;端口等&#xff0c;软件怎么用 参数设置 点击"设置"菜单&#xff0c;选择"扫描参数"或者直接点击工具栏的蓝色按钮进入扫…

驱动开发:内核特征码扫描PE代码段

在笔者上一篇文章《驱动开发&#xff1a;内核特征码搜索函数封装》中为了定位特征的方便我们封装实现了一个可以传入数组实现的SearchSpecialCode定位函数&#xff0c;该定位函数其实还不能算的上简单&#xff0c;本章LyShark将对特征码定位进行简化&#xff0c;让定位变得更简…

【操作系统】设备驱动

本文为学习李治军老师《操作系统原理、实现与实践》第八章的总结&#xff0c;主要讲述显示器、键盘设备驱动。 参考资料&#xff1a; 哈工大李治军老师操作系统mooc视频&#xff1b;实践项目解析。 第八章 设备驱动 设备驱动的基本原理 外设工作原理 从CPU开始&#xff1a;…

UOS上扫描仪驱动笔记

之前自己总结了打印机驱动以及打印连接协议等等&#xff0c;但对扫描仪一直没怎么注意&#xff0c;一是客户扫描仪用的少&#xff0c;二是遇到的客户扫描仪都能正常驱动&#xff0c;下载个扫描易就搞定了&#xff0c;尤其是很多一体机官网也带了驱动&#xff0c;但实际上现在的…

关于 打印机可打印无法扫描报错“使用该设备需要WIA驱动程序,请从安装CS或从...” 的解决方法

若该文为原创文章&#xff0c;转载请注明原文出处 本文章博客地址&#xff1a;https://hpzwl.blog.csdn.net/article/details/128906315 红胖子(红模仿)的博文大全&#xff1a;开发技术集合&#xff08;包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软…

如何在Windows 10中修复卡住的“扫描和修复驱动器”

Windows 10 卡在扫描和修复驱动器 卡在扫描和修复驱动器很快就变成了Windows 10计算机用户最头痛的问题。chkdsk的扫描和修复驱动器似乎永远不会完成&#xff0c;停滞在一定数字的百分比不前进。 「我的联强计算机Window 10启动时卡在『正在扫描和修复驱动器(C:): 已完成11%』…