MATLAB计算卫星星下点轨迹

MATLAB计算卫星星下点轨迹,涵盖多个坐标系转换。

一、MATLAB实现:完整星下点轨迹计算

主程序:satellite_subpoint_trajectory.m

matlab 复制代码
%% 卫星星下点轨迹计算 - 多坐标系方法
clear; clc; close all;

% 设置参数
sim_duration = 100 * 60; % 仿真时长(秒)
time_step = 60;         % 时间步长(秒)
num_points = floor(sim_duration / time_step);

% 轨道参数(示例:近地轨道)
orbit_params.a = 7000e3;       % 半长轴 (m)
orbit_params.e = 0.001;        % 偏心率(近圆轨道)
orbit_params.i = deg2rad(60);  % 轨道倾角 (rad)
orbit_params.Omega0 = deg2rad(0);  % 初始升交点赤经 (rad)
orbit_params.omega = deg2rad(0);   % 近地点幅角 (rad)
orbit_params.M0 = 0;           % 初始平近点角 (rad)

% 物理常数
constants.mu = 3.986004418e14;     % 地球引力常数 (m^3/s^2)
constants.omega_e = 7.2921150e-5;  % 地球自转角速度 (rad/s)
constants.Re = 6378137.0;          % 地球赤道半径 (m)
constants.f = 1/298.257223563;     % 扁率
constants.J2 = 1.08262668e-3;      % J2摄动项

% 计算星下点轨迹
fprintf('计算星下点轨迹...\n');
trajectory = compute_subpoint_trajectory(orbit_params, constants, ...
                                         sim_duration, time_step);

% 绘制结果
plot_trajectory_results(trajectory, orbit_params, constants);

% 保存数据
save_subpoint_data(trajectory, 'subpoint_trajectory.mat');

函数1:计算星下点轨迹 compute_subpoint_trajectory.m

matlab 复制代码
function trajectory = compute_subpoint_trajectory(orbit, const, duration, dt)
% 计算卫星星下点轨迹
% 输入:
%   orbit - 轨道参数结构体
%   const - 物理常数结构体
%   duration - 仿真时长(秒)
%   dt - 时间步长(秒)
% 输出:
%   trajectory - 轨迹数据结构体

times = 0:dt:duration;
n_points = length(times);

% 预分配数组
lat = zeros(n_points, 1);
lon = zeros(n_points, 1);
alt = zeros(n_points, 1);
r_eci = zeros(3, n_points);
r_ecef = zeros(3, n_points);

% 计算平均角速度
n = sqrt(const.mu / orbit.a^3);  % rad/s

fprintf('进度: ');
for i = 1:n_points
    t = times(i);
    
    % 显示进度
    if mod(i, ceil(n_points/10)) == 0
        fprintf('%d%% ', round(100*i/n_points));
    end
    
    % 1. 计算当前平近点角
    M = orbit.M0 + n * t;
    
    % 2. 解开普勒方程求偏近点角
    E = solve_kepler(orbit.e, M);
    
    % 3. 计算真近点角
    nu = 2 * atan2(sqrt(1+orbit.e)*sin(E/2), sqrt(1-orbit.e)*cos(E/2));
    
    % 4. 考虑J2摄动引起的升交点赤经变化
    Omega_dot = -1.5 * const.J2 * (const.Re/orbit.a)^2 * n * cos(orbit.i) / (1-orbit.e^2)^2;
    Omega = orbit.Omega0 + Omega_dot * t;
    
    % 5. 计算ECI坐标
    r_eci(:, i) = orbital_to_eci(orbit.a, orbit.e, orbit.i, Omega, orbit.omega, nu);
    
    % 6. ECI转ECEF
    r_ecef(:, i) = eci_to_ecef(r_eci(:, i), t, const.omega_e);
    
    % 7. ECEF转经纬高
    [lat(i), lon(i), alt(i)] = ecef_to_lla(r_ecef(:, i), const.Re, const.f);
end
fprintf('\n完成!\n');

% 将经度调整到[-180, 180]范围
lon = mod(lon + 180, 360) - 180;

% 构建轨迹结构体
trajectory.times = times;
trajectory.lat = lat;
trajectory.lon = lon;
trajectory.alt = alt;
trajectory.r_eci = r_eci;
trajectory.r_ecef = r_ecef;
end

函数2:解开普勒方程 solve_kepler.m

matlab 复制代码
function E = solve_kepler(e, M, tol)
% 解开普勒方程 E - e*sin(E) = M
% 使用牛顿-拉夫逊方法

if nargin < 3
    tol = 1e-12;  % 默认精度
end

% 初始估计值
if M < pi
    E = M + e/2;
else
    E = M - e/2;
end

% 迭代求解
max_iter = 100;
for iter = 1:max_iter
    f = E - e*sin(E) - M;
    f_prime = 1 - e*cos(E);
    
    delta = f / f_prime;
    E = E - delta;
    
    if abs(delta) < tol
        break;
    end
end
end

函数3:轨道根数转ECI orbital_to_eci.m

matlab 复制代码
function r_eci = orbital_to_eci(a, e, i, Omega, omega, nu)
% 将轨道根数转换为ECI坐标
% 输入:
%   a - 半长轴 (m)
%   e - 偏心率
%   i - 倾角 (rad)
%   Omega - 升交点赤经 (rad)
%   omega - 近地点幅角 (rad)
%   nu - 真近点角 (rad)
% 输出:
%   r_eci - ECI坐标 [x; y; z] (m)

% 计算半正焦弦
p = a * (1 - e^2);

% 计算轨道半径
r = p / (1 + e * cos(nu));

% 轨道平面内的坐标
x_o = r * cos(nu);
y_o = r * sin(nu);
z_o = 0;

% 旋转矩阵
R_Omega = [cos(Omega)  sin(Omega) 0;
          -sin(Omega)  cos(Omega) 0;
           0           0          1];

R_i = [1    0       0;
       0 cos(i)  sin(i);
       0 -sin(i) cos(i)];

R_omega = [cos(omega)  sin(omega) 0;
          -sin(omega)  cos(omega) 0;
           0           0          1];

% 组合旋转
R = R_Omega * R_i * R_omega;

% 转换到ECI坐标系
r_orbit = [x_o; y_o; z_o];
r_eci = R' * r_orbit;  % 注意:这里是转置
end

函数4:ECI转ECEF eci_to_ecef.m

matlab 复制代码
function r_ecef = eci_to_ecef(r_eci, t, omega_e)
% 将ECI坐标转换为ECEF坐标
% 输入:
%   r_eci - ECI坐标 [x; y; z] (m)
%   t - 从参考时刻起的时间 (s)
%   omega_e - 地球自转角速度 (rad/s)
% 输出:
%   r_ecef - ECEF坐标 [x; y; z] (m)

% 计算地球自转角度(考虑格林尼治恒星时)
% 简化:假设参考时刻0时,春分点在格林尼治子午线上
theta = omega_e * t;

% 旋转矩阵(绕Z轴旋转)
R = [cos(theta)   sin(theta)   0;
    -sin(theta)   cos(theta)   0;
       0              0        1];

r_ecef = R * r_eci;
end

函数5:ECEF转经纬高 ecef_to_lla.m

matlab 复制代码
function [lat, lon, alt] = ecef_to_lla(r_ecef, Re, f)
% 将ECEF坐标转换为经纬高(WGS84椭球)
% 输入:
%   r_ecef - ECEF坐标 [x; y; z] (m)
%   Re - 地球赤道半径 (m)
%   f - 扁率
% 输出:
%   lat - 纬度 (度)
%   lon - 经度 (度)
%   alt - 高度 (m)

x = r_ecef(1);
y = r_ecef(2);
z = r_ecef(3);

% WGS84参数
e2 = 2*f - f^2;  % 第一偏心率平方

% 计算经度
lon = atan2(y, x);

% 计算地心纬度(初始估计)
p = sqrt(x^2 + y^2);
phi = atan2(z, p);

% 迭代计算大地纬度
max_iter = 50;
tol = 1e-12;
N = Re;  % 初始化

for iter = 1:max_iter
    sin_phi = sin(phi);
    N = Re / sqrt(1 - e2 * sin_phi^2);
    h = p / cos(phi) - N;
    phi_new = atan2(z, p * (1 - e2 * N/(N + h)));
    
    if abs(phi_new - phi) < tol
        phi = phi_new;
        break;
    end
    phi = phi_new;
end

% 计算高度
sin_phi = sin(phi);
N = Re / sqrt(1 - e2 * sin_phi^2);
h = p / cos(phi) - N;

% 转换为度
lat = rad2deg(phi);
lon = rad2deg(lon);
alt = h;
end

函数6:考虑J2摄动的改进版本 compute_with_j2.m

matlab 复制代码
function [r_eci_new, v_eci_new] = propagate_orbit_j2(r_eci, v_eci, dt, mu, Re, J2)
% 考虑J2摄动的轨道传播
% 使用4阶Runge-Kutta方法

% 状态向量
y0 = [r_eci; v_eci];

% 定义微分方程
dydt = @(t, y) orbit_ode_j2(t, y, mu, Re, J2);

% Runge-Kutta 4阶方法
k1 = dt * dydt(0, y0);
k2 = dt * dydt(0, y0 + 0.5*k1);
k3 = dt * dydt(0, y0 + 0.5*k2);
k4 = dt * dydt(0, y0 + k3);

y_new = y0 + (k1 + 2*k2 + 2*k3 + k4)/6;

r_eci_new = y_new(1:3);
v_eci_new = y_new(4:6);
end

function dydt = orbit_ode_j2(~, y, mu, Re, J2)
% 考虑J2摄动的轨道微分方程

r = y(1:3);
v = y(4:6);

% 计算位置矢量模长
r_norm = norm(r);
r_sq = r_norm^2;

% J2摄动加速度
z = r(3);
factor = 1.5 * J2 * mu * Re^2 / (r_norm^5);
ax_j2 = factor * r(1) * (5*z^2/r_sq - 1);
ay_j2 = factor * r(2) * (5*z^2/r_sq - 1);
az_j2 = factor * r(3) * (5*z^2/r_sq - 3);

a_j2 = [ax_j2; ay_j2; az_j2];

% 中心引力加速度
a_central = -mu * r / (r_norm^3);

% 总加速度
a_total = a_central + a_j2;

dydt = [v; a_total];
end

函数7:绘制结果 plot_trajectory_results.m

matlab 复制代码
function plot_trajectory_results(traj, orbit, const)
% 绘制星下点轨迹结果

fprintf('生成图形...\n');

% 创建图形窗口
figure('Position', [100, 100, 1200, 800]);

% 子图1:世界地图上的轨迹
subplot(2, 2, 1);
worldmap('World');
load coastlines;
plotm(coastlat, coastlon, 'k');
hold on;
scatterm(traj.lat, traj.lon, 10, traj.times/60, 'filled');
colorbar;
title('星下点轨迹(世界地图)');
xlabel('经度 (度)');
ylabel('纬度 (度)');

% 子图2:经纬度二维图
subplot(2, 2, 2);
plot(traj.lon, traj.lat, 'b-', 'LineWidth', 1);
hold on;
plot(traj.lon(1), traj.lat(1), 'go', 'MarkerSize', 10, 'MarkerFaceColor', 'g');
plot(traj.lon(end), traj.lat(end), 'ro', 'MarkerSize', 10, 'MarkerFaceColor', 'r');
grid on;
xlabel('经度 (度)');
ylabel('纬度 (度)');
title('星下点轨迹(经纬度)');
legend('轨迹', '起点', '终点');
axis equal;

% 子图3:高度变化
subplot(2, 2, 3);
plot(traj.times/60, traj.alt/1000, 'b-', 'LineWidth', 2);
grid on;
xlabel('时间 (分钟)');
ylabel('高度 (km)');
title('卫星高度变化');

% 子图4:3D轨道视图
subplot(2, 2, 4);
% 绘制地球
[Earth_x, Earth_y, Earth_z] = sphere(50);
Earth_x = Earth_x * const.Re/1e6;
Earth_y = Earth_y * const.Re/1e6;
Earth_z = Earth_z * const.Re/1e6;
surf(Earth_x, Earth_y, Earth_z, 'FaceAlpha', 0.5, 'EdgeColor', 'none');
hold on;
colormap(winter);

% 绘制轨道(ECI坐标系)
plot3(traj.r_eci(1,:)/1e6, traj.r_eci(2,:)/1e6, traj.r_eci(3,:)/1e6, ...
      'r-', 'LineWidth', 2);
plot3(traj.r_eci(1,1)/1e6, traj.eci(2,1)/1e6, traj.r_eci(3,1)/1e6, ...
      'go', 'MarkerSize', 10, 'MarkerFaceColor', 'g');
plot3(traj.r_eci(1,end)/1e6, traj.r_eci(2,end)/1e6, traj.r_eci(3,end)/1e6, ...
      'ro', 'MarkerSize', 10, 'MarkerFaceColor', 'r');

axis equal;
grid on;
xlabel('X (10^6 m)');
ylabel('Y (10^6 m)');
zlabel('Z (10^6 m)');
title('3D轨道视图(ECI坐标系)');
view(45, 30);

% 添加信息框
info_str = sprintf(['轨道参数:\n' ...
                    '半长轴: %.1f km\n' ...
                    '偏心率: %.4f\n' ...
                    '倾角: %.1f°\n' ...
                    '周期: %.1f 分钟'], ...
                    orbit.a/1000, orbit.e, rad2deg(orbit.i), ...
                    2*pi*sqrt(orbit.a^3/const.mu)/60);
annotation('textbox', [0.02, 0.02, 0.25, 0.1], ...
           'String', info_str, 'BackgroundColor', 'white');
end

函数8:保存数据 save_subpoint_data.m

matlab 复制代码
function save_subpoint_data(trajectory, filename)
% 保存星下点轨迹数据

% 提取数据
data.time_min = trajectory.times / 60;  % 转换为分钟
data.latitude = trajectory.lat;
data.longitude = trajectory.lon;
data.altitude_km = trajectory.alt / 1000;
data.eci_pos = trajectory.r_eci;
data.ecef_pos = trajectory.r_ecef;

% 保存到MAT文件
save(filename, 'data');
fprintf('数据已保存到: %s\n', filename);

% 可选:导出为CSV文件用于其他软件
csv_data = [data.time_min', data.latitude, data.longitude, data.altitude_km];
csvwrite('subpoint_trajectory.csv', csv_data);

% 写入文件头
fid = fopen('subpoint_trajectory.csv', 'r+');
if fid ~= -1
    fseek(fid, 0, 'bof');
    fprintf(fid, 'Time(min),Latitude(deg),Longitude(deg),Altitude(km)\n');
    fclose(fid);
    fprintf('CSV文件已生成: subpoint_trajectory.csv\n');
end
end

二、实用工具函数

快速计算工具 quick_subpoint_calculation.m

matlab 复制代码
function [lat, lon] = quick_subpoint_calculation(orbit_elements, UTC_time)
% 快速计算给定时刻的星下点
% 输入:
%   orbit_elements - 轨道根数 [a; e; i; Omega; omega; M0] (SI单位,弧度)
%   UTC_time - UTC时间 (datetime对象)
% 输出:
%   lat, lon - 星下点经纬度

% 常数
mu = 3.986004418e14;
omega_e = 7.2921150e-5;
Re = 6378137.0;

% 提取轨道参数
a = orbit_elements(1);
e = orbit_elements(2);
i = orbit_elements(3);
Omega0 = orbit_elements(4);
omega = orbit_elements(5);
M0 = orbit_elements(6);

% 计算平近点角
n = sqrt(mu / a^3);
t = seconds(UTC_time - datetime(2000,1,1,12,0,0)); % 简化时间计算
M = M0 + n * t;

% 解开普勒方程
E = solve_kepler(e, M);
nu = 2 * atan2(sqrt(1+e)*sin(E/2), sqrt(1-e)*cos(E/2));

% 考虑地球自转
Omega = Omega0 + omega_e * t;

% 计算ECI坐标
r_eci = orbital_to_eci(a, e, i, Omega, omega, nu);

% 转换为ECEF
theta = omega_e * t;
R = [cos(theta) sin(theta) 0; -sin(theta) cos(theta) 0; 0 0 1];
r_ecef = R * r_eci;

% 转换为经纬高
[lat, lon, ~] = ecef_to_lla(r_ecef, Re, 1/298.257223563);
end

三、使用示例

示例1:基本计算

matlab 复制代码
% 定义轨道参数(ISS近似轨道)
orbit.a = 6778e3;  % 约420km高度
orbit.e = 0.001;
orbit.i = deg2rad(51.64);  % ISS倾角
orbit.Omega0 = deg2rad(0);
orbit.omega = deg2rad(0);
orbit.M0 = 0;

% 计算1个轨道周期的轨迹
T = 2*pi*sqrt(orbit.a^3/3.986004418e14);  % 轨道周期
trajectory = compute_subpoint_trajectory(orbit, T, 10);

示例2:批量处理多个卫星

matlab 复制代码
% 定义多个卫星的轨道
satellites = {
    struct('a', 7000e3, 'e', 0.001, 'i', deg2rad(60), 'name', 'Sat1'),
    struct('a', 7200e3, 'e', 0.002, 'i', deg2rad(45), 'name', 'Sat2'),
    struct('a', 7500e3, 'e', 0.0015, 'i', deg2rad(30), 'name', 'Sat3')
};

figure;
for k = 1:length(satellites)
    sat = satellites{k};
    traj = compute_subpoint_trajectory(sat, 90*60, 30);
    plot(traj.lon, traj.lat, 'LineWidth', 1.5);
    hold on;
end
legend({satellites.name});

参考代码 卫星星下点轨迹的计算,使用多个坐标系计算 www.youwenfan.com/contentcsn/83778.html

四、关键说明

  1. 坐标系定义

    • ECI:以春分点为基准,不随地球旋转
    • ECEF:随地球旋转,X轴指向本初子午线
    • 地理坐标系:WGS84椭球模型
  2. 时间系统

    • 使用国际原子时(TAI)简化计算
    • 实际应用中需要考虑UTC跳秒
  3. 精度考虑

    • 基本版本忽略高阶摄动
    • J2版本考虑地球扁率主要影响
    • 高精度需求需使用SGP4模型
  4. 性能优化

    • 预分配数组提高计算效率
    • 可使用并行计算处理多个卫星
相关推荐
_OP_CHEN2 小时前
【算法基础篇】(三十一)动态规划之基础背包问题:从 01背包到完全背包,带你吃透背包问题的核心逻辑
算法·蓝桥杯·动态规划·背包问题·01背包·完全背包·acm/icpc
子不语1802 小时前
Matlab读取文件
前端·javascript·matlab
长安er2 小时前
LeetCode876/141/142/143 快慢指针应用:链表中间 / 环形 / 重排问题
数据结构·算法·leetcode·链表·双指针·环形链表
Aaron15882 小时前
电子战侦察干扰技术在反无人机领域的技术浅析
算法·fpga开发·硬件架构·硬件工程·无人机·基带工程
二狗哈3 小时前
Cesium快速入门15:图元Primitive创建图像物体
开发语言·javascript·3d·webgl·cesium·地图可视化
lljss20203 小时前
C# 定时器类实现1s定时器更新UI
开发语言·c#
白杨攻城狮3 小时前
C# 关于 barierr 心得
开发语言·c#
zhglhy3 小时前
Jaccard相似度算法原理及Java实现
java·开发语言·算法
catchadmin3 小时前
PHP 8.5 容器化实战指南
开发语言·php