站心直角坐标系转经纬高

该博客详细介绍了如何在C#中实现地心坐标与站心直角坐标的相互转换,包括从经纬高到地心坐标,再从地心坐标到经纬高的转换过程。此外,还提供了站心直角坐标系中相对坐标的计算方法,并给出了具体的代码实现。转换过程中涉及到了椭球体模型、迭代法等概念,适用于地理信息系统或导航定位等领域。

序:网上很多算法,基本都是错的,还得去找论文才行。原理就不讲了,我会贴出论文引用。

1.转换过程

(1)确定站心直角坐标系的原点(X0,Y0,Z0)=(0,0,0)的经纬高(B0,L0,H0)作为基准点。

(2)将基准点(B0,L0,H0)转成地心坐标。

(3)将站心直角坐标系的目标点(X1,Y1,Z1)转成地心坐标(eX1,eY1,eZ1)。

(4)将地心坐标(eX1,eY1,eZ1)转成经纬高(B1,L1,H1)。

2.C#代码

    /// <summary>
        /// 使用WGS84椭球体
    /// </summary>
    public class CoorTransform
    {
        #region C#实现方法/三角函数及迭代法
        /// <summary>
        /// 地心坐标转经纬高
        /// </summary>
        /// <param name="X"></param>
        /// <param name="Y"></param>
        /// <param name="Z"></param>
        /// <param name="aAxis"></param>
        /// <param name="bAxis"></param>
        /// <returns></returns>
        public static Vector3D XYZtoBLH(double X, double Y, double Z, double aAxis = 6378137,             double bAxis = 6356752.3142)
		{
            double targetH, targetB, targetL;
            double e1 = (Math.Pow(aAxis, 2) - Math.Pow(bAxis, 2)) / Math.Pow(aAxis, 2);
            double e2 = (Math.Pow(aAxis, 2) - Math.Pow(bAxis, 2)) / Math.Pow(bAxis, 2);

            double S = Math.Sqrt(Math.Pow(X, 2) + Math.Pow(Y, 2));
            double cosL = X / S;
            double B = 0;
            double L = 0;

            L = Math.Acos(cosL);
            L = Math.Abs(L);

            double tanB = Z / S;
            B = Math.Atan(tanB);
            double c = aAxis * aAxis / bAxis;
            double preB0 = 0.0;
            double ll = 0.0;
            double N = 0.0;
            //迭代计算纬度
            do
            {
                preB0 = B;
                ll = Math.Pow(Math.Cos(B), 2) * e2;
                N = c / Math.Sqrt(1 + ll);

                tanB = (Z + N * e1 * Math.Sin(B)) / S;
                B = Math.Atan(tanB);
            } while (Math.Abs(preB0 - B) >= 0.0000000001);

            ll = Math.Pow(Math.Cos(B), 2) * e2;
            N = c / Math.Sqrt(1 + ll);

            targetH = S / Math.Cos(B) - N;// * (1 - e1);
            targetB = B * 180 / Math.PI;
            targetL = L * 180 / Math.PI;
            return new Vector3D(targetB, targetL, targetH);
        }
        /// <summary>
        /// 经纬高转地心坐标
        /// </summary>
        /// <param name="B"></param>
        /// <param name="L"></param>
        /// <param name="H"></param>
        /// <param name="aAxis"></param>
        /// <param name="bAxis"></param>
        /// <returns></returns>
		public static Vector3D BLHtoXYZ(double B, double L, double H, double aAxis = 6378137, double bAxis = 6356752.3142)
		{
			double targetX, targetY, targetZ;
			double dblD2R = Math.PI / 180.0;
            double f = 1 / 298.257223563;
            double e2 = 2 * f - f * f;
            //double e1 = Math.Sqrt(Math.Pow(aAxis, 2) - Math.Pow(bAxis, 2)) / Math.Pow(aAxis, 2);

            double W = Math.Sqrt(1 - e2 * Math.Sin(B * dblD2R) * Math.Sin(B * dblD2R));
            double N = aAxis / W;
			//double N = aAxis / Math.Sqrt(1.0 - Math.Pow(e1, 2) * Math.Pow(Math.Sin(B * dblD2R), 2));
			targetX = (N + H) * Math.Cos(B * dblD2R) * Math.Cos(L * dblD2R);
			targetY = (N + H) * Math.Cos(B * dblD2R) * Math.Sin(L * dblD2R);
			targetZ = (N * (1.0 - e2) + H) * Math.Sin(B * dblD2R);
			return new Vector3D(targetX, targetY, targetZ);
		}
        /// <summary>
        /// 计算站心直角坐标系中的相对坐标在地心坐标系中的坐标
        /// </summary>
        /// <param name="X0">站心原点的地心坐标X</param>
        /// <param name="Y0">站心原点的地心坐标Y</param>
        /// <param name="Z0">站心原点的地心坐标Z</param>
        /// <param name="B0">站心原点的纬度</param>
        /// <param name="L0">站心原点的经度</param>
        /// <param name="H0">站心原点的高度</param>
        /// <param name="rX">相对站心原点的目标坐标X</param>
        /// <param name="rY">相对站心原点的目标坐标Y</param>
        /// <param name="rZ">相对站心原点的目标坐标Z</param>
        /// <returns></returns>
        public static Vector3D CalRelaXYZBasedOnBLH(double X0,double Y0,double Z0,double B0,double L0,double H0,
            double rX,double rY,double rZ)
        {
            double dblD2R = Math.PI / 180.0;
            var AX = -Math.Sin(L0 * dblD2R) * rX + -Math.Sin(B0 * dblD2R) * Math.Cos(L0 * dblD2R) * rY + Math.Cos(B0 * dblD2R) * Math.Cos(L0 * dblD2R) * rZ;
            var AY = -Math.Cos(L0 * dblD2R) * rX + -Math.Sin(B0 * dblD2R) * Math.Sin(L0 * dblD2R) * rY + Math.Cos(B0 * dblD2R) * Math.Sin(L0 * dblD2R) * rZ;
            var AZ = 0 + Math.Cos(B0 * dblD2R) * rY + Math.Sin(B0 * dblD2R) * rZ;
            var relaX = AX + X0;
            var relaY = AY + Y0;
            var relaZ = AZ + Z0;
            return new Vector3D(relaX, relaY, relaZ);
        }
        #endregion
    }

3.转换代码,为了直观变量名使用中文

double 基准点纬度 = 34, 基准点经度 = 112, 基准点高 = 300;
double 目标站心坐标X = 0, 目标站心坐标Y = 100000, 目标站心坐标Z = 8000;
var 站心原点的地心坐标 = CoorTransform.BLHtoXYZ(基准点纬度, 基准点经度, 基准点高);
var 目标的地心坐标 = CoorTransform.CalRelaXYZBasedOnBLH(站心原点的地心坐标.X, 站心原点的地心坐标.Y, 站心原点的地心坐标.Z, 基准点纬度, 基准点经度, 基准点高, 目标站心坐标X, 目标站心坐标Y, 目标站心坐标Z);
var 目标的纬经高 = CoorTransform.XYZtoBLH(目标的地心坐标.X, 目标的地心坐标.Y, 目标的地心坐标.Z);

4.结果

 [注:]

1.直角坐标单位皆为米。

2.本文的站心直角坐标为东、北、天,即X+ => 东,Y+ => 北,Z+ => 天。如果使用北、天、东注意下转换。

引用

[1]凌震莹.大地坐标系与站心地平直角坐标系的坐标转换[J].声学与电子工程,2009(04):31-34.

<think> 根据用户的需求,用户希望了解在Matlab中实现地坐标系(ECEF,Earth-Centered, Earth-Fixed)换为经纬坐标系(经纬度和度)的方法。根据提供的引用,特别是引用[3]和引用[5],我们可以给出以下解答。 引用[3]提到了一个Matlab函数`ecef2lla`,它可以将ECEF坐标换为纬度、经度和度(LLA: Latitude, Longitude, Altitude)。该函数基于WGS84地球模型。 引用[5]则展示了一段手动换的代码,通过求解方程组来实现换,但这种方法较为复杂。 因此,推荐使用现成的函数`ecef2lla`,因为它已经经过验证且效。 ### 使用`ecef2lla`函数进行换 在Matlab中,可以使用以下步骤: 1. 确保安装了Matlab的Mapping Toolbox,因为`ecef2lla`函数是该工具箱的一部分。 2. 调用`ecef2lla`函数,输入ECEF坐标(X, Y, Z),单位为米,输出为纬度(degrees)、经度(degrees)和度(meters)。 示例代码: ```matlab % 定义ECEF坐标(单位:米) X = 3027710.628; % 示例数据 Y = 5632557.121; % 示例数据 Z = 2578105.524; % 示例数据 % 换为经纬(LLA) [lat, lon, alt] = ecef2lla([X, Y, Z]); % 显示结果 fprintf('纬度: %.6f°\n经度: %.6f°\n度: %.3f米\n', lat, lon, alt); ``` ### 如果没有Mapping Toolbox 如果没有Mapping Toolbox,可以自己实现换函数。引用[5]提供了一种方法,但需要注意,其中使用了符号求解,效率可能较低。实际上,换可以通过迭代计算完成。以下是一个基于WGS84椭球模型的换函数: ```matlab function [lat, lon, alt] = ecef2lla_manual(x, y, z) % WGS84参数 a = 6378137.0; % 半长轴(米) f = 1/298.257223563; % 扁率 e2 = 2*f - f*f; % 第一偏率的平方 % 计算经度(直接计算) lon = atan2d(y, x); % 初始化纬度 p = sqrt(x*x + y*y); lat0 = atan2d(z, p*(1-e2)); % 初始估计 lat = lat0; % 迭代计算纬度 for i = 1:10 N = a / sqrt(1 - e2*sind(lat)^2); alt = p / cosd(lat) - N; lat_new = atan2d(z, p*(1 - e2*N/(N+alt))); if abs(lat_new - lat) < 1e-10 lat = lat_new; break; end lat = lat_new; end alt = p / cosd(lat) - N; end ``` ### 注意事项 1. 上述手动实现函数仅作为参考,实际使用时需要验证。 2. 官方函数`ecef2lla`更加精确且效,建议优先使用。 ### 相关资源 如果需要下载现成的换代码,可以参考引用[3]提供的项目地址:[ECEF坐标换为纬度经度和度Matlab开发](https://gitcode.com/open-source-toolkit/32dfb) [^3]。 §§相关问题§§ 1. 如何将经纬坐标换为地坐标系(ECEF)? 2. 在Matlab中,除了WGS84,还支持哪些地球椭球模型? 3. 坐标换中的度是相对于椭球面还是大地水准面? </think> ### Matlab实现地坐标系(ECEF)经纬坐标系(LLA) 在Matlab中,地直角坐标系(ECEF,Earth-Centered, Earth-Fixed)到经纬坐标系(LLA,Latitude/Longitude/Altitude)的换可通过以下两种方法实现: --- #### **方法1:使用内置函数`ecef2lla`(推荐)** ```matlab % 定义ECEF坐标(单位:米) X = 3027710.628; % 示例ECEF-X坐标 Y = 5632557.121; % 示例ECEF-Y坐标 Z = 2578105.524; % 示例ECEF-Z坐标 % 换为经纬(LLA) [lat, lon, alt] = ecef2lla([X, Y, Z]); % 显示结果 disp(['纬度: ', num2str(lat), '°']); disp(['经度: ', num2str(lon), '°']); disp(['度: ', num2str(alt), '米']); ``` **说明**: 1. `ecef2lla`函数来自**Mapping Toolbox**,基于WGS84椭球模型[^3][^5] 2. 输入为ECEF坐标向量`[X,Y,Z]`,输出顺序:纬度、经度、度(米) 3. 度为**椭球**(Ellipsoidal Height) --- #### **方法2:手动实现换(无工具箱时)** ```matlab function [lat, lon, alt] = ecef2lla_manual(X, Y, Z) % WGS84参数 a = 6378137.0; % 半长轴(米) f = 1/298.257223563; % 扁率 e2 = 2*f - f*f; % 第一偏率的平方 % 计算经度(直接求解) lon = atan2d(Y, X); % 迭代计算纬度和度 p = sqrt(X^2 + Y^2); lat0 = atan2d(Z, p*(1-e2)); % 初始估计 for i = 1:10 % 迭代10次 N = a / sqrt(1 - e2*sind(lat0)^2); alt = p / cosd(lat0) - N; lat = atan2d(Z, p*(1 - e2*N/(N + alt))); if abs(lat - lat0) < 1e-10 break; end lat0 = lat; end end ``` **使用示例**: ```matlab [lat, lon, alt] = ecef2lla_manual(X, Y, Z); ``` --- #### **关键公式与参数** 1. **迭代核方程**: $$ \phi_{\text{new}} = \tan^{-1}\left( \frac{Z}{p} \cdot \frac{1}{1 - e^2 \frac{N}{N + h}} \right) $$ 其中: - $\phi$:纬度,$N = \frac{a}{\sqrt{1 - e^2 \sin^2\phi}}$(卯酉圈曲率半径) - $h$:度,$p = \sqrt{X^2 + Y^2}$ 2. **WGS84参数**: - 半长轴 $a = 6378137.0 \text{ m}$ - 扁率 $f = 1/298.257223563$ - 偏率平方 $e^2 = 6.69437999014 \times 10^{-3}$ [^4][^5] --- #### **注意事项** 1. 经度范围:$[-180^\circ, 180^\circ]$,纬度范围:$[-90^\circ, 90^\circ]$ 2. 度为**椭球**,若要获取**海拔**需叠加大地水准面模型(如EGM96) 3. 推荐优先使用官方函数`ecef2lla`以保证精度[^3] 如需获取完整代码实现,可参考开源项目:[ECEF坐标LLA的Matlab实现](https://gitcode.com/open-source-toolkit/32dfb)[^3] ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值