优化三维空间定位法及C语言快捷实现

一、三维空间定位原理

假设我们知道自身到定位基站的距离di (i=1 2 3 4…)并且知道定位基站的坐标,那么我们就可以在空间上建立n个以基站坐标为圆心,距离为半径的空间球体,球体方程如下。其中a,b,c为基站坐标,r为被定位者距离基站的绝对距离。

假定,我们拥有三个定位基站,那么我们就可以得到一个方程组。该方程组最终可以解得两组实数数据。此时高度无法准确的确定,如果要确定准确的高度,我们就要在引入一个基站,构成一个拥有四个方程的方程组。解这个方程组就可以得到我们想要的坐标了。

但是这里就会产生一个问题:使用单片机解一个含有三个参数的二元二次方程组显然这样做不太方面,而且如果被定位者过多或基站过多就会导致坐标更新延迟等问题。所以笔者基于这一问题对计算进行优化处理。

二、定高

首先我们先检测被定位者的相对高度。这里设置两个基站A和B,它们的坐标只有Z轴不同,即一上一下两个基站如图所示,此时空间两个球体相交与空间一个一个空间平面,并且该平面平行于绝对平面(地面)。故我们只需要考虑该平面的高度即可

此时我们得到简化后的方程组为

化简后联立得

此时高度为

三、空间定位到平面定位

在第二节我们已经使用了两个基站,并得到了被定位者的高度。这里我们在设置两个基站C和D,并保证C和D与A或B在同一平面。然后我们将被定位者的坐标,利用第二节得到的高度投影到ACD所在的平面,这样我们就可以将空间坐标转换到平面来进行计算,即不在考虑Z轴的问题。此时我们列出两个方程

化简联立方程组,消去XY的平方项得到方程a

该方程的物理意义及为两圆在平面中相交所得到的平面直线。同理化简并联立1 3 得到方程 b

综上方程a和方程b我们可以写成矩阵的形式如下

这里我们令为矩阵A。为矩阵B。既可得到坐标为

四、验证

这里笔者先使用了CAD绘制了一个坐标,再使用MATLAB进行计算和验证。

clear
clc
A = [0 0];
B = [100 0];
C = [0 100];%定义坐标

La = 70;
Lb = 74.17;
Lc = 67.86;%定义基站距定位点距离

D = [2*A(1)-2*B(1) 2*A(2)-2*B(2);
     2*A(1)-2*C(1) 2*A(2)-2*C(2)]; %定义参数矩阵
 
XY = [0;
      0];
  
Z = [(Lb^2 - La^2)+(A(1)^2 - B(1)^2)+(A(2)^2 - B(2)^2);
     (Lc^2 - La^2)+(A(1)^2 - C(1)^2)+(A(2)^2 - C(2)^2)];
 
XY = D^-1 * Z


%%===========运行结果==============%%

XY =

   46.9941
   51.4751

五、使用C语言实现

采用C语言实现主要是需要用C语言做矩阵的逆和矩阵乘法,具体代码如下

//================计算矩阵的逆================//
#include<stdio.h>
#define N 10
double Det(double arcs[N][N],int n)//按第一行展开计算|A|
{
    double ans = 0;
    double temp[N][N];
    int i,j,k;
	double t;
    if(n==1)
    {
        return arcs[0][0];
    }
    for(i=0;i<n;i++)
    {
        for(j=0;j<n-1;j++)
        {
            for(k=0;k<n-1;k++)
            {
                temp[j][k] = arcs[j+1][(k>=i)?k+1:k];

            }
        }
        t = Det(temp,n-1);
        if(i%2==0)
        {
            ans += arcs[0][i]*t;
        }
        else
        {
            ans -=  arcs[0][i]*t;
        }
    }
    return ans;
}
void Minor(double arcs[N][N],double ans[N][N],int n)//计算每一行每一列的每个元素所对应的余子式,组成A*
{
	int i,j,k,t;
    double temp[N][N];
    if(n==1)
    {
        ans[0][0] = 1;
        return;
    }
    for(i=0;i<n;i++)
    {
        for(j=0;j<n;j++)
        {
            for(k=0;k<n-1;k++)
            {
                for(t=0;t<n-1;t++)
                {
                    temp[k][t] = arcs[k>=i?k+1:k][t>=j?t+1:t];
                }
            }


            ans[j][i]  =  Det(temp,n-1);
            if((i+j)%2 == 1)
            {
                ans[j][i] = - ans[j][i];
            }
        }
    }
}
int main()
{
    double A[N][N] = {{-200,0},{0,-200}};
    double iA[N][N];  
    int i,j;
	double dA;
    dA = Det(A,2);
    Minor(A,iA,2);
    for(i=0;i<2;++i)
    {
        for(j=0;j<2;++j)
        {
            printf("%f ", A[i][j]);
        }
        printf("\n");
    }
    printf("\n");
    for(i=0;i<2;++i)
    {
        for(j=0;j<2;++j)
        {
            printf("%f ",(iA[i][j]/dA));
        }
        printf("\n");
    }
    return 0;
}
//=======================矩阵乘法===================//
#include "stdio.h"

void main()
{
	double Max1[2][2]={{7,8},{1,5}};
	double Max2[2][1]={{0.5},{0.3}};
	double Max3[2][1];
	unsigned char i,j;
	double ans=0;
	for(i=0;i<2;i++)
	{
		for(j=0;j<2;j++)
		{
			ans += Max1[i][j]*Max2[j][0];
		}
		Max3[i][0] = ans;
		ans = 0;
	}
	for(i=0;i<2;i++)
	{
		for(j=0;j<1;j++)
		{
			printf("%f ",Max3[i][j]);
		}
		printf("\n");
	}

}

六、总结

该方法只是笔者的一个想法并没有具体使用,不知道实际具有误差的情况下该方法精度如何,待笔者后续测试。笔者水平有限如有纰漏尽请指正。

  • 3
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
空间多边定位法(Multilateration)是一种通过多个节点的距离信息来估计目标位置的方法。在C语言实现空间多边定位法需要使用数学计算库和一些基本的C语言知识。 以下是一个简单的C语言程序,用于实现空间多边定位法: ```c #include <stdio.h> #include <math.h> #define N 4 //节点数 #define MAX_ITERATIONS 100 //最大迭代次数 #define EPSILON 1e-6 //收敛误差 typedef struct { double x, y, z; } point_t; point_t nodes[N] = {{0, 0, 0}, {10, 0, 0}, {0, 10, 0}, {0, 0, 10}}; //节点坐标 double distances[N] = {5, 8, 9, 7}; //节点到目标点的距离 double distance(point_t p1, point_t p2) { return sqrt(pow(p1.x - p2.x, 2) + pow(p1.y - p2.y, 2) + pow(p1.z - p2.z, 2)); } point_t multilateration() { int i, j, k; double d[N]; point_t p, p_prev; double error = 1; int iterations = 0; //使用节点1作为初始值 p = nodes[0]; while (error > EPSILON && iterations < MAX_ITERATIONS) { //计算每个节点到当前估计点的距离 for (i = 0; i < N; i++) { d[i] = distance(p, nodes[i]); } //更新估计点 p_prev = p; p.x = p.y = p.z = 0; for (i = 0; i < N; i++) { double w = distances[i] / d[i]; p.x += w * nodes[i].x; p.y += w * nodes[i].y; p.z += w * nodes[i].z; } //计算误差 error = distance(p, p_prev); iterations++; } return p; } int main() { point_t p = multilateration(); printf("目标点坐标:(%f, %f, %f)\n", p.x, p.y, p.z); return 0; } ``` 在上面的程序中,我们定义了一个`point_t`结构体用于表示三维坐标点,一个`nodes`数组用于存储节点的坐标,一个`distances`数组用于存储节点到目标点的距离。`distance`函数用于计算两个坐标点之间的距离。 在`multilateration`函数中,我们使用节点1作为初始估计点,然后在每次迭代中计算每个节点到当前估计点的距离,并使用距离权重更新估计点。在每次迭代中,我们计算当前估计点与上一次估计点之间的距离作为误差,并将其与预设的收敛误差进行比较。如果误差小于收敛误差或达到最大迭代次数,则停止迭代并返回估计点。 在`main`函数中,我们调用`multilateration`函数获取目标点的坐标,并将其输出到屏幕上。 请注意,上面的程序只是一个简单的示例,实际中可能需要根据具体情况进行修改和优化

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值