152 lines
5.7 KiB
Matlab
Executable File
152 lines
5.7 KiB
Matlab
Executable File
classdef HelperNTNPositionEstimate
|
|
%HelperNTNPositionEstimate Class defining the supporting functions used
|
|
%in the receiver position estimation in NTN example
|
|
%
|
|
% Note: This is an undocumented class and its API and/or
|
|
% functionality may change in subsequent releases.
|
|
|
|
% Copyright 2024-2025 The MathWorks, Inc.
|
|
|
|
methods (Static)
|
|
function out = instantposition(s, v, r, rDot)
|
|
% OUT = instantposition(S,V,R,RDOT) returns the possible
|
|
% position OUT using satellite position S, satellite velocity
|
|
% V, range R, and range-rate RDOT. S and V are in Earth
|
|
% Centered Earth Fixed (ECEF) coordinate system. R is in m and
|
|
% RDOT is in m/s. OUT is a 3-by-2 matrix with each column
|
|
% corresponding to a possible position in LLA (Latitude,
|
|
% Longitude, Altitude).
|
|
|
|
tolerance = 1e-4;
|
|
max_iter_refine = 1000;
|
|
% Earth Parameters
|
|
r_E = 6378137; % Equatorial radius (meters)
|
|
r_p = 6356752; % Polar radius (meters)
|
|
|
|
% Initialize two r_c values with random values
|
|
r_c_1 = (r_E - r_p) * rand();
|
|
r_c_2 = r_c_1; % Starting both from the same value (can be different if needed)
|
|
|
|
% Refinement loop for two solutions
|
|
for iter = 1:max_iter_refine
|
|
prev_r_c_1 = r_c_1;
|
|
prev_r_c_2 = r_c_2;
|
|
|
|
% Compute geometric parameters
|
|
r_s2 = dot(s,s); % Squared norm of position vector
|
|
|
|
% Linear system for refinement
|
|
A = [s(1) s(2); v(1) v(2)];
|
|
b_1 = 0.5*(r_s2 + r_c_1^2 - r^2);
|
|
b_2 = 0.5*(r_s2 + r_c_2^2 - r^2);
|
|
c = dot(s,v) - r*rDot;
|
|
|
|
% Solve the parameters for r_c_1 and r_c_2
|
|
mat_1 = [b_1, s(3); c, v(3)];
|
|
mat_2 = [b_2, s(3); c, v(3)];
|
|
|
|
params_1 = A \ mat_1;
|
|
params_2 = A \ mat_2;
|
|
|
|
% Extract parameters for the first solution
|
|
alpha_1 = params_1(1);
|
|
beta_1 = params_1(3);
|
|
gamma_1 = params_1(2);
|
|
delta_1 = params_1(4);
|
|
|
|
% Extract parameters for the second solution
|
|
alpha_2 = params_2(1);
|
|
beta_2 = params_2(3);
|
|
gamma_2 = params_2(2);
|
|
delta_2 = params_2(4);
|
|
|
|
% Calculate discriminant for both solutions
|
|
numerator_1 = alpha_1 * beta_1 + gamma_1 * delta_1;
|
|
discriminant_1 = numerator_1^2 - (1 + delta_1^2 + beta_1^2) * (alpha_1^2 + gamma_1^2 - r_c_1^2);
|
|
|
|
numerator_2 = alpha_2 * beta_2 + gamma_2 * delta_2;
|
|
discriminant_2 = numerator_2^2 - (1 + delta_2^2 + beta_2^2) * (alpha_2^2 + gamma_2^2 - r_c_2^2);
|
|
|
|
% Handle negative discriminant by regenerating r_c
|
|
if discriminant_1 < 0
|
|
r_c_1 = r_p + (r_E - r_p) * rand();
|
|
continue;
|
|
end
|
|
if discriminant_2 < 0
|
|
r_c_2 = r_p + (r_E - r_p) * rand();
|
|
continue;
|
|
end
|
|
|
|
% Compute z-coordinates for both solutions
|
|
z_hat_1 = (numerator_1 + sqrt(discriminant_1)) / (1 + delta_1^2 + beta_1^2);
|
|
z_hat_2 = (numerator_2 - sqrt(discriminant_2)) / (1 + delta_2^2 + beta_2^2);
|
|
|
|
% Compute x and y coordinates for both solutions
|
|
x_hat_1 = alpha_1 - beta_1 * z_hat_1;
|
|
y_hat_1 = gamma_1 - delta_1 * z_hat_1;
|
|
|
|
x_hat_2 = alpha_2 - beta_2 * z_hat_2;
|
|
y_hat_2 = gamma_2 - delta_2 * z_hat_2;
|
|
|
|
% Convert to LLA
|
|
lla_1 = ecef2llaLocal([x_hat_1; y_hat_1; z_hat_1]);
|
|
lla_2 = ecef2llaLocal([x_hat_2; y_hat_2; z_hat_2]);
|
|
|
|
% Recalculate r_c for refined solutions
|
|
dr_1 = sind(lla_1(1))^2 + cosd(lla_1(1))^2 * (r_p / r_E)^2;
|
|
r_c_1 = sqrt(r_p^2 / dr_1);
|
|
|
|
dr_2 = sind(lla_2(1))^2 + cosd(lla_2(1))^2 * (r_p / r_E)^2;
|
|
r_c_2 = sqrt(r_p^2 / dr_2);
|
|
|
|
% Check convergence for both solutions
|
|
if abs(r_c_1 - prev_r_c_1) < tolerance && abs(r_c_2 - prev_r_c_2) < tolerance
|
|
break;
|
|
end
|
|
end
|
|
out = [];
|
|
if discriminant_1 > 0
|
|
out = lla_1(:);
|
|
end
|
|
if discriminant_2 > 0
|
|
out = [out(:) lla_2(:)];
|
|
end
|
|
end
|
|
|
|
function error = positionerror(originalPos,estimatedPos)
|
|
% ERR = positionerror(ORIGINALPOS,ESTIMATEDPOS) computes the
|
|
% position errors ERR for given original position ORIGINALPOS
|
|
% and estimated positions ESTIMATEDPOS. Original position and
|
|
% estimated positions are in LLA. ESTIMATEDPOS is 3-by-N matrix
|
|
% with N being the number of positions.
|
|
|
|
% Convert the positions to ECEF
|
|
posECEF = lla2ecefLocal([originalPos estimatedPos]);
|
|
error = vecnorm(posECEF(:,1)-posECEF(:,2:end));
|
|
end
|
|
end
|
|
end
|
|
|
|
function lla = ecef2llaLocal(ecef)
|
|
% Output Latitude (degrees), Longitude (degrees), and Altitude (meters)
|
|
|
|
tmp = matlabshared.orbit.internal.Transforms.itrf2geographic(ecef);
|
|
% Convert to degrees and get the LLA coordinates
|
|
lla = [rad2deg(tmp(1,1:end)); ...
|
|
rad2deg(tmp(2,1:end)); ...
|
|
tmp(3,1:end)];
|
|
|
|
end
|
|
|
|
function ecef = lla2ecefLocal(lla)
|
|
% Output ECEF: X (meters), Y (meters), and Z (meters)
|
|
|
|
% Convert to radians
|
|
lla = [deg2rad(lla(1,1:end)); ...
|
|
deg2rad(lla(2,1:end)); ...
|
|
lla(3,1:end)];
|
|
% Get ECEF coordinates
|
|
ecef = matlabshared.orbit.internal.Transforms.geographic2itrf(lla);
|
|
|
|
end
|