ECEF与ENU坐标系定义及C语言实现

一、ECEF与ENU坐标系定义

  1. ECEF坐标系(地心地固坐标系)
  • 原点:地球质心
  • X轴:指向本初子午线与赤道交点
  • Y轴:在赤道平面内与X轴垂直
  • Z轴:指向北极
  • 数学表示: P e c e f = ( x , y , z ) P_{ecef} = (x, y, z) Pecef=(x,y,z)
  1. ENU坐标系(东北天坐标系)
  • 原点:本地参考点
  • E轴:指向东方
  • N轴:指向北方
  • U轴:垂直地面向上
  • 数学表示: P e n u = ( e , n , u ) P_{enu} = (e, n, u) Penu=(e,n,u)

二、坐标转换数学原理

  1. 地理坐标转ECEF:
    { x = ( N + h ) cos ⁡ ϕ cos ⁡ λ y = ( N + h ) cos ⁡ ϕ sin ⁡ λ z = ( N ( 1 − e 2 ) + h ) sin ⁡ ϕ \begin{cases} x = (N + h)\cos\phi\cos\lambda \\ y = (N + h)\cos\phi\sin\lambda \\ z = (N(1-e^2)+h)\sin\phi \end{cases} x=(N+h)cosϕcosλy=(N+h)cosϕsinλz=(N(1e2)+h)sinϕ
    其中:
  • N = a 1 − e 2 sin ⁡ 2 ϕ N = \frac{a}{\sqrt{1-e^2\sin^2\phi}} N=1e2sin2ϕ a(卯酉圈曲率半径)
  • e 2 = 2 f − f 2 e^2 = 2f - f^2 e2=2ff2(椭球偏心率平方)
  • a = 6378137 m a=6378137m a=6378137m(WGS84长半轴)
  • f = 1 / 298.257223563 f=1/298.257223563 f=1/298.257223563(WGS84扁率)
  1. ECEF转ENU:
    [ e n u ] = [ − sin ⁡ λ cos ⁡ λ 0 − sin ⁡ ϕ cos ⁡ λ − sin ⁡ ϕ sin ⁡ λ cos ⁡ ϕ cos ⁡ ϕ cos ⁡ λ cos ⁡ ϕ sin ⁡ λ sin ⁡ ϕ ] [ x − x 0 y − y 0 z − z 0 ] \begin{bmatrix} e \\ n \\ u \end{bmatrix} = \begin{bmatrix} -\sin\lambda & \cos\lambda & 0 \\ -\sin\phi\cos\lambda & -\sin\phi\sin\lambda & \cos\phi \\ \cos\phi\cos\lambda & \cos\phi\sin\lambda & \sin\phi \end{bmatrix} \begin{bmatrix} x-x_0 \\ y-y_0 \\ z-z_0 \end{bmatrix} enu = sinλsinϕcosλcosϕcosλcosλsinϕsinλcosϕsinλ0cosϕsinϕ xx0yy0zz0

三、C语言实现(保存为ecef2enu.c)

#include <stdio.h>
#include <math.h>#define WGS84_A 6378137.0
#define WGS84_F 1/298.257223563typedef struct { double x, y, z; } ECEF;
typedef struct { double lat, lon, alt; } Geodetic;
typedef struct { double e, n, u; } ENU;ECEF geodetic_to_ecef(Geodetic geo) {double a = WGS84_A;double f = WGS84_F;double e2 = 2*f - f*f;double sinphi = sin(geo.lat);double cosphi = cos(geo.lat);double N = a / sqrt(1 - e2*sinphi*sinphi);ECEF ecef;ecef.x = (N + geo.alt) * cosphi * cos(geo.lon);ecef.y = (N + geo.alt) * cosphi * sin(geo.lon);ecef.z = (N*(1-e2) + geo.alt) * sinphi;return ecef;
}ENU ecef_to_enu(ECEF target, Geodetic ref_geo) {ECEF ref_ecef = geodetic_to_ecef(ref_geo);double dx = target.x - ref_ecef.x;double dy = target.y - ref_ecef.y;double dz = target.z - ref_ecef.z;double sinphi = sin(ref_geo.lat);double cosphi = cos(ref_geo.lat);double sinlam = sin(ref_geo.lon);double coslam = cos(ref_geo.lon);ENU enu;enu.e = -sinlam*dx + coslam*dy;enu.n = -sinphi*coslam*dx - sinphi*sinlam*dy + cosphi*dz;enu.u = cosphi*coslam*dx + cosphi*sinlam*dy + sinphi*dz;return enu;
}int main() {// 北京参考点(39.9042°N, 116.4074°E,海拔43m)Geodetic ref = {.lat = 39.9042 * M_PI/180,.lon = 116.4074 * M_PI/180,.alt = 43};// 生成测试数据(实际应用时可从文件读取)for(int i=0; i<5; i++) {Geodetic target_geo = {.lat = ref.lat + 0.01*i,.lon = ref.lon + 0.01*i,.alt = ref.alt + 10*i};ECEF target_ecef = geodetic_to_ecef(target_geo);ENU enu = ecef_to_enu(target_ecef, ref);printf("ENU: E=%.3fm, N=%.3fm, U=%.3fm\n", enu.e, enu.n, enu.u);}return 0;
}

编译执行:

gcc ecef2enu.c -lm -o ecef2enu && ./ecef2enu

四、Python验证代码

import numpy as np
import matplotlib.pyplot as plt
from pyproj import Transformer
from subprocess import check_output# 生成100个测试点
np.random.seed(42)
ref_lat, ref_lon = 39.9042, 116.4074
d_lats = np.random.uniform(-0.1, 0.1, 100)
d_lons = np.random.uniform(-0.1, 0.1, 100)
alts = np.random.uniform(0, 1000, 100)# 运行C程序获取结果
c_output = check_output(["./ecef2enu"]).decode().strip().split('\n')
c_enu = [list(map(float, line.split()[2::2])) for line in c_output]# 使用pyproj计算
ecef_trans = Transformer.from_crs(4326, 4978)
enu_trans = Transformer.from_crs(4326, 4467, authority="EPSG",lon_0=ref_lon, lat_0=ref_lat, h_0=0)errors = []
for i in range(100):# Python计算结果lat = ref_lat + d_lats[i]lon = ref_lon + d_lons[i]alt = alts[i]# pyproj计算ENUecef = ecef_trans.transform(lat, lon, alt)enu_py = enu_trans.transform(lat, lon, alt)# 计算误差enu_c = c_enu[i] if i <5 else [0,0,0] # 仅示例前5个errors.append(np.array(enu_py) - np.array(enu_c))# 可视化
errors = np.array(errors)
plt.figure(figsize=(12,4))plt.subplot(131)
plt.hist(errors[:,0], bins=20)
plt.title('East Error Distribution')
plt.xlabel('Meters')plt.subplot(132)
plt.hist(errors[:,1], bins=20)
plt.title('North Error Distribution')plt.subplot(133)
plt.scatter(errors[:,0], errors[:,1], alpha=0.6)
plt.xlabel('East Error')
plt.ylabel('North Error')
plt.tight_layout()
plt.savefig('enu_errors.png')
plt.show()

五、验证结果分析

  1. 误差直方图显示各方向误差分布
  2. 散点图展示平面误差的相关性
  3. 典型误差应小于1e-4米(数值计算误差)

该实现完整展示了从理论到实践的全流程,可通过调整测试点数量和分布进行更严格的验证。实际工程应用中需考虑坐标系的旋转顺序、大地水准面模型等更多细节。

(验证代码还有BUG,不能直接运行,但是我肝不了了,该天再调了,晚安,吗喀巴卡)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/73070.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

sql语句分页的关键字是?

在 SQL 中&#xff0c;分页通常是通过限制查询结果的数量并指定从哪一行开始获取数据来实现的。不同的数据库系统使用不同的分页关键字。 以下是常见数据库系统的分页关键字&#xff1a; MySQL / PostgreSQL / SQLite 使用 LIMIT 和 OFFSET 来进行分页&#xff1a; LIMIT 限…

大模型中的剪枝、蒸馏是什么意思?

环境&#xff1a; 剪枝 蒸馏 问题描述&#xff1a; 大模型中的剪枝、蒸馏是什么意思&#xff1f; 解决方案&#xff1a; 大模型的剪枝&#xff08;Pruning&#xff09;和蒸馏&#xff08;Distillation&#xff09;是两种常见的模型优化技术&#xff0c;用于减少模型的大小…

初次体验Tauri和Sycamore(3)通道实现

​ 原创作者&#xff1a;庄晓立&#xff08;LIIGO&#xff09; 原创时间&#xff1a;2025年03月10日&#xff08;发布时间&#xff09; 原创链接&#xff1a;https://blog.csdn.net/liigo/article/details/146159327 版权所有&#xff0c;转载请注明出处。 20250310 LIIGO备注&…

代码随想录|二叉树|07二叉树周末总结

对前面01~06二叉树内容进行小结&#xff0c;直接看下面的总结文档&#xff1a; 本周小结&#xff01;&#xff08;二叉树&#xff09; | 代码随想录

蓝耘赋能通义万相 2.1:用 C++ 构建高效 AI 视频生成生态

目录 开篇&#xff1a;AI 视频生成新时代的号角 通义万相 2.1&#xff1a;AI 视频生成的领军者 核心技术揭秘 功能特点展示 与其他模型的全面对比 C&#xff1a;高效编程的基石 C 的发展历程与特性 C 在 AI 领域的广泛应用 通义万相 2.1 与 C 的完美融合 融合的意义与…

【一句话经验】ubuntu vi/vim 模式自动设置为paste

从centos过来&#xff0c;发现ubutun有些地方不习惯&#xff0c;尤其是vi的粘贴&#xff0c;默认自动进去了代码模式&#xff0c;导致每次粘贴必须得set paste&#xff0c;否则会出现问题。 解决办法非常简单&#xff0c;按照下面命令执行即可&#xff1a; cd ~ echo "…

自然语言处理文本分析:从词袋模型到认知智能的进化之旅

清晨&#xff0c;当智能音箱准确识别出"播放周杰伦最新专辑"的模糊语音指令时&#xff1b;午间&#xff0c;企业舆情系统自动标记出十万条评论中的负面情绪&#xff1b;深夜&#xff0c;科研人员用GPT-4解析百万篇论文发现新材料线索——这些场景背后&#xff0c;是自…

《Python基础教程》附录B笔记:Python参考手册

《Python基础教程》第1章笔记&#x1f449;https://blog.csdn.net/holeer/article/details/143052930 附录B Python参考手册 Python标准文档是完整的参考手册。本附录只是一个便利的速查表&#xff0c;当你开始使用Python进行编程后&#xff0c;它可帮助你唤醒记忆。 B.1 表…

uniapp+Vue3 组件之间的传值方法

一、父子传值&#xff08;props / $emit 、ref / $refs&#xff09; 1、props / $emit 父组件通过 props 向子组件传递数据&#xff0c;子组件通过 $emit 触发事件向父组件传递数据。 父组件&#xff1a; // 父组件中<template><view class"container">…

【MySQL篇】MySQL基本查询详解

目录 前言&#xff1a; 1&#xff0c;Create 1.1&#xff0c;单行数据全列插入 1.2&#xff0c;单行数据指定列插入 1.3&#xff0c;多行数据全列插入 1.4&#xff0c;多行数据指定列插入 1.5&#xff0c;插入否则更新 1.6&#xff0c;替换 2&#xff0c;Retrieve …

【Python入门】一篇掌握Python中的字典(创建、访问、修改、字典方法)【详细版】

&#x1f308; 个人主页&#xff1a;十二月的猫-CSDN博客 &#x1f525; 系列专栏&#xff1a; &#x1f3c0;《Python/PyTorch极简课》_十二月的猫的博客-CSDN博客 &#x1f4aa;&#x1f3fb; 十二月的寒冬阻挡不了春天的脚步&#xff0c;十二点的黑夜遮蔽不住黎明的曙光 目…

每日一题——两数相加

两数相加 问题描述问题分析解题思路代码实现代码解析注意事项示例运行总结 问题描述 给定两个非空链表&#xff0c;表示两个非负整数。链表中的每个节点存储一个数字&#xff0c;数字的存储顺序为逆序&#xff08;即个位在链表头部&#xff09;。要求将这两个数字相加&#xff…

制作自定义镜像

1. 确定软件包 确定自己的环境都需要哪些命令&#xff0c;然后&#xff0c;从镜像文件或者yum源下载响应的安装包。 bash基本是必选的 &#xff08;bash-5.1.8-10.oe2203sp2.aarch64.rpm&#xff09; vim也是有必要的 &#xff08;vim-enhanced-9.0-15.oe2203sp2.aarch64.rpm…

WHAT - 前端性能指标

目录 核心 Web Vitals&#xff08;Core Web Vitals&#xff09;加载性能指标网络相关指标交互和响应性能指标内存与效率指标推荐的监控工具优化策略与建议推荐学习路线 作为前端开发者&#xff0c;理解并掌握关键的性能指标对优化 Web 应用至关重要。 以下是前端性能优化中常见…

C++20 模块:告别头文件,迎接现代化的模块系统

文章目录 引言一、C20模块简介1.1 传统头文件的局限性1.2 模块的出现 二、模块的基本概念2.1 模块声明2.2 模块接口单元2.3 模块实现单元 三、模块的优势3.1 编译时间大幅减少3.2 更好的依赖管理3.3 命名空间隔离 四、如何使用C20模块4.1 编译器支持4.2 示例项目4.3 编译和运行…

Apache Hudi 性能测试报告

一、测试背景 数据湖作为一个集中化的数据存储仓库,支持结构化、半结构化以及非结构化等多种数据格式,数据来源包含数据库数据、增量数据、日志数据以及数仓上的存量数据等。数据湖能够将这些不同来源、不同格式的数据集中存储和管理在高性价比的分布式存储系统中,对外提供…

sql靶场5-6关(报错注入)保姆级教程

目录 sql靶场5-6关&#xff08;报错注入&#xff09;保姆级教程 1.第五关 1.步骤一&#xff08;闭合&#xff09; 2.步骤二&#xff08;列数&#xff09; 3.报错注入深解 4.报错注入格式 5.步骤三&#xff08;数据库表名&#xff09; 6.常用函数 7.步骤四&#xff08;表…

OSPF-单区域的配置

一、单区域概念&#xff1a; 单区域OSPF中&#xff0c;整个网络被视为一个区域&#xff0c;区域ID通常为0&#xff08;骨干区域&#xff09;。所有的路由器都在这个区域内交换链路状态信息。 补充知识点&#xff1a; OSPF为何需要loopback接口&#xff1a; 1.Loopback接口的…

LeetCode100之二叉树的直径(543)--Java

1.问题描述 给你一棵二叉树的根节点&#xff0c;返回该树的 直径 。 二叉树的 直径 是指树中任意两个节点之间最长路径的 长度 。这条路径可能经过也可能不经过根节点 root 。 两节点之间路径的 长度 由它们之间边数表示。 示例1 输入&#xff1a;root [1,2,3,4,5] 输出&#…

C语言每日一练——day_4

引言 针对初学者&#xff0c;每日练习几个题&#xff0c;快速上手C语言。第四天。&#xff08;连续更新中&#xff09; 采用在线OJ的形式 什么是在线OJ&#xff1f; 在线判题系统&#xff08;英语&#xff1a;Online Judge&#xff0c;缩写OJ&#xff09;是一种在编程竞赛中用…