刘志明
多个测站的地月距离计算(VBA)程序
2025-8-28 06:54
阅读:134

Public Type ecef

x As Double

y As Double

z As Double

End Type

' 定义结构体存储ENU坐标

Public Type enu

e As Double

n As Double

u As Double

End Type

' 定义结构体存储观测点

Public Type ObservationPoint

ecef As ecef

enu As enu

End Type

Private Sub CommandButton1_Click()

' 定义结构体存储ECEF坐标

Dim Obs1(1 To 50) As ObservationPoint

Dim target As ecef

Dim RR As Double, RR1 As Double, JD As Double, L As Long, Nobs As Long

Dim Alpha As Double

With Sheet5

RR = 30000000

Nobs = .Cells(1, 4)

' 设置观测点1的ECEF坐标和ENU坐标

For i = 1 To Nobs

Obs1(i).ecef.x = .Cells(2 * (i - 1) + 1, 1)

Obs1(i).ecef.y = .Cells(2 * (i - 1) + 1, 2)

Obs1(i).ecef.z = .Cells(2 * (i - 1) + 1, 3)

Next i

L = 0

Alpha = .Cells(1, 5)

JD = .Cells(1, 6)

100 If L <= 500000 Then

For ik = 1 To Nobs

Obs1(ik).enu.e = .Cells(2 * ik, 1) * RR * Alpha

Obs1(ik).enu.n = .Cells(2 * ik, 2) * RR * Alpha

Obs1(ik).enu.u = .Cells(2 * ik, 3) * RR * Alpha

Next ik

' 计算目标点ECEF坐标

target = CalculateTargetECEF(Obs1(), Nobs)

RR1 = Sqr(target.x ^ 2 + target.y ^ 2 + target.z ^ 2)

If Abs((RR - RR1) / RR1) > JD Then

RR = RR1

L = L + 1

GoTo 100

End If

End If

.Cells(3, 8) = "L=" & L

' 输出结果

.Cells(1, 8) = "Target ECEF coordinates:"

.Cells(2, 8) = target.x

.Cells(2, 9) = target.y

.Cells(2, 10) = target.z

End With

End Sub

' 主函数:计算目标点ECEF坐标

Function CalculateTargetECEF(Obs1() As ObservationPoint, Nobs As Long) As ecef

Dim A(1 To 150, 1 To 3) As Double

Dim b(1 To 150) As Double

Dim i As Integer

' 构建设计矩阵A和观测向量b

For i = 1 To Nobs

Dim R(1 To 3, 1 To 3) As Double

Dim obs As ObservationPoint

obs = Obs1(i)

' 计算旋转矩阵

CalculateRotationMatrix obs.ecef, R

' 填充A矩阵

A(3 * (i - 1) + 1, 1) = R(1, 1)

A(3 * (i - 1) + 1, 2) = R(1, 2)

A(3 * (i - 1) + 1, 3) = R(1, 3)

A(3 * (i - 1) + 2, 1) = R(2, 1)

A(3 * (i - 1) + 2, 2) = R(2, 2)

A(3 * (i - 1) + 2, 3) = R(2, 3)

A(3 * (i - 1) + 3, 1) = R(3, 1)

A(3 * (i - 1) + 3, 2) = R(3, 2)

A(3 * (i - 1) + 3, 3) = R(3, 3)

' 填充b向量

b(3 * (i - 1) + 1) = R(1, 1) * obs.ecef.x + R(1, 2) * obs.ecef.y + R(1, 3) * obs.ecef.z + obs.enu.e

b(3 * (i - 1) + 2) = R(2, 1) * obs.ecef.x + R(2, 2) * obs.ecef.y + R(2, 3) * obs.ecef.z + obs.enu.n

b(3 * (i - 1) + 3) = R(3, 1) * obs.ecef.x + R(3, 2) * obs.ecef.y + R(3, 3) * obs.ecef.z + obs.enu.u

Next i

' 使用最小二乘法求解

CalculateTargetECEF = LeastSquares(A, b, Nobs)

End Function

' 计算旋转矩阵(ECEF到ENU)

Sub CalculateRotationMatrix(ecef As ecef, ByRef R() As Double)

Dim lat As Double, lon As Double

Dim A As Double, e2 As Double

Dim h As Double

h = 0

' WGS84椭球参数

A = 6378137# ' 半长轴

e2 = 0.00669437999014 ' 第一偏心率的平方

' 计算经纬度

Call ECEFToGeodetic(ecef, lat, lon, h, A, e2)

h = h + A

' 计算旋转矩阵

R(1, 1) = -Sin(lon)

R(1, 2) = -Sin(lat) * Cos(lon)

R(1, 3) = Cos(lat) * Cos(lon)

R(2, 1) = Cos(lon)

R(2, 2) = -Sin(lat) * Sin(lon)

R(2, 3) = Cos(lat) * Sin(lon)

R(3, 1) = 0

R(3, 2) = Cos(lat)

R(3, 3) = Sin(lat)

End Sub

' ECEF转大地坐标(简化实现)

Sub ECEFToGeodetic(ecef As ecef, ByRef lat As Double, ByRef lon As Double, ByRef height As Double, A As Double, e2 As Double)

Dim p As Double, theta As Double

Dim n As Double

p = Sqr(ecef.x * ecef.x + ecef.y * ecef.y)

lon = Atn2(ecef.y, ecef.x)

' 迭代计算纬度

lat = Atn2(ecef.z, p * (1 - e2))

Do

n = A / Sqr(1 - e2 * Sin(lat) * Sin(lat))

theta = Atn2(ecef.z + e2 * n * Sin(lat), p)

If Abs(lat - theta) < 0.0000000001 Then Exit Do

lat = theta

Loop

height = p / Cos(lat) - n

End Sub

' 反正切函数

Function Atn2(y As Double, x As Double) As Double

If x > 0 Then

Atn2 = Atn(y / x)

ElseIf x < 0 Then

Atn2 = Atn(y / x) + Sgn(y) * 3.14159265358979

Else

Atn2 = Sgn(y) * 3.14159265358979 / 2

End If

End Function

' 最小二乘法求解

Function LeastSquares(A() As Double, b() As Double, Nobs As Long) As ecef

Dim AT(1 To 3, 1 To 500) As Double

Dim ATA(1 To 3, 1 To 3) As Double

Dim ATb(1 To 3) As Double

Dim i As Integer, j As Integer, k As Integer

' 计算A的转置

For i = 1 To 3 * Nobs

For j = 1 To 3

AT(j, i) = A(i, j)

Next j

Next i

' 计算ATA = A^T * A

For i = 1 To 3

For j = 1 To 3

ATA(i, j) = 0

For k = 1 To 3 * Nobs

ATA(i, j) = ATA(i, j) + AT(i, k) * A(k, j)

Next k

Next j

Next i

' 计算ATb = A^T * b

For i = 1 To 3

ATb(i) = 0

For k = 1 To 3 * Nobs

ATb(i) = ATb(i) + AT(i, k) * b(k)

Next k

Next i

' 求解方程组ATA * x = ATb

' 这里使用高斯消元法

LeastSquares = SolveLinearSystem(ATA, ATb)

End Function

' 求解线性方程组(高斯消元法)

Function SolveLinearSystem(A() As Double, b() As Double) As ecef

Dim n As Integer: n = 3

Dim Augmented(1 To 3, 1 To 4) As Double

Dim x(1 To 3) As Double

Dim i As Integer, j As Integer, k As Integer

Dim factor As Double

' 构建增广矩阵

For i = 1 To n

For j = 1 To n

Augmented(i, j) = A(i, j)

Next j

Augmented(i, n + 1) = b(i)

Next i

' 前向消元

For i = 1 To n - 1

For j = i + 1 To n

factor = Augmented(j, i) / Augmented(i, i)

For k = i To n + 1

Augmented(j, k) = Augmented(j, k) - factor * Augmented(i, k)

Next k

Next j

Next i

' 回代

x(n) = Augmented(n, n + 1) / Augmented(n, n)

For i = n - 1 To 1 Step -1

x(i) = Augmented(i, n + 1)

For j = i + 1 To n

x(i) = x(i) - Augmented(i, j) * x(j)

Next j

x(i) = x(i) / Augmented(i, i)

Next i

' 返回结果

SolveLinearSystem.x = x(1)

SolveLinearSystem.y = x(2)

SolveLinearSystem.z = x(3)

End Function

转载本文请联系原作者获取授权,同时请注明本文来自刘志明科学网博客。

链接地址:https://wap.sciencenet.cn/blog-3556836-1499370.html?mobile=1

收藏

分享到:

当前推荐数:1
推荐人:
推荐到博客首页
网友评论4 条评论
确定删除指定的回复吗?
确定删除本博文吗?