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
四、关键说明
-
坐标系定义:
- ECI:以春分点为基准,不随地球旋转
- ECEF:随地球旋转,X轴指向本初子午线
- 地理坐标系:WGS84椭球模型
-
时间系统:
- 使用国际原子时(TAI)简化计算
- 实际应用中需要考虑UTC跳秒
-
精度考虑:
- 基本版本忽略高阶摄动
- J2版本考虑地球扁率主要影响
- 高精度需求需使用SGP4模型
-
性能优化:
- 预分配数组提高计算效率
- 可使用并行计算处理多个卫星