liuzhiming69的个人博客分享 http://blog.sciencenet.cn/u/liuzhiming69

博文

地月距离计算VBA程序(迭代法)

已有 114 次阅读 2025-8-26 09:32 |系统分类:科研笔记

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 As ObservationPoint

Dim obs2 As ObservationPoint

Dim target As ecef

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

Dim Alpha As Double

With Sheet5

RR = 30000000

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

obs1.ecef.x = .Cells(1, 1)

obs1.ecef.y = .Cells(1, 2)

obs1.ecef.z = .Cells(1, 3)

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

obs2.ecef.x = .Cells(3, 1)

obs2.ecef.y = .Cells(3, 2)

obs2.ecef.z = .Cells(3, 3)

L = 0

Alpha = 1

JD = .Cells(7, 2)

100 If L <= 100000 Then

obs1.enu.e = .Cells(2, 1) * RR

obs1.enu.n = .Cells(2, 2) * RR

obs1.enu.u = .Cells(2, 3) * RR

obs2.enu.e = .Cells(4, 1) * RR

obs2.enu.n = .Cells(4, 2) * RR

obs2.enu.u = .Cells(4, 3) * RR

' 计算目标点ECEF坐标

target = CalculateTargetECEF(obs1, obs2)

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

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

RR = RR1 * Alpha

L = L + 1

GoTo 100

End If

End If

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

' 输出结果

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

.Cells(6, 1) = target.x

.Cells(6, 2) = target.y

.Cells(6, 3) = target.z

End With

End Sub

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

Function CalculateTargetECEF(obs1 As ObservationPoint, obs2 As ObservationPoint) As ecef

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

Dim b(1 To 6) As Double

Dim i As Integer

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

For i = 1 To 2

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

Dim obs As ObservationPoint

If i = 1 Then

obs = obs1

Else

obs = obs2

End If

' 计算旋转矩阵

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) = obs.ecef.x + obs.enu.e

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

b(3 * (i - 1) + 3) = obs.ecef.z + obs.enu.u

Next i

' 使用最小二乘法求解

CalculateTargetECEF = LeastSquares(A, b)

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) As ecef

Dim AT(1 To 3, 1 To 6) 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 6

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 6

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 6

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

输入数据:

obs1 x,y,z(ECEF坐标)

a a a -1724234.11, 2869607.451, 5420517.6

obs1 E,N,U

-0.53604746, -0.00030588 ,0.9046023

obs2 x,y,z(ECEF坐标)

-2889117.01, 4808298.162 ,3020416

obs2 E,N,U

-0.47683355 -0.25674841 0.9013114 a

计算结果为:

target 坐标(ECEF)

x,y,z

a a a 189804220.6,193115117.5, 265726095 a

r=37.9wKm,地月距离



https://wap.sciencenet.cn/blog-3556836-1499141.html

上一篇:ENU坐标系转换成ECEF坐标系公式(修正)
下一篇:单点求地月距离VBA程序
收藏 IP: 121.28.181.*| 热度|

1 王涛

该博文允许注册用户评论 请点击登录 评论 (4 个评论)

数据加载中...

Archiver|手机版|科学网 ( 京ICP备07017567号-12 )

GMT+8, 2025-8-29 03:58

Powered by ScienceNet.cn

Copyright © 2007- 中国科学报社

返回顶部