Обнаружение и отслеживание спутникового созвездия LEO с наземными радарами

Этот пример показывает, как импортировать файл Двухлинейного Элемента (TLE) спутниковой совокупности, симулировать радиолокационные обнаружения созвездия и отслеживать созвездие.

Задача заселения и ведения каталога космических объектов, вращающихся вокруг Земли, имеет решающее значение для наблюдения за космосом. Эта задача состоит из нескольких процессов: обнаружение и идентификация новых объектов и добавление их в каталог, обновление известных орбит объектов в каталоге, отслеживание изменений орбиты на протяжении их жизни и предсказание повторных входов в атмосферу. В этом примере мы изучаем, как обнаружить и отследить новые спутники и добавить их в каталог.

Чтобы гарантировать безопасные операции в пространстве и предотвратить столкновения с другими спутниками или известными обломками, важно правильно обнаруживать и отслеживать вновь запущенные спутники. Космические агентства обычно делятся предстартовой информацией, которую можно использовать для выбора стратегии поиска. Обычно используется стратегия поиска спутников на низкой околоземной орбите (НОО), состоящая из радиолокационных систем заборного типа. Радиолокационная система заборного типа ищет конечный объем в пространстве и обнаруживает спутники, когда они проходят через его поле зрения. Эта стратегия может быстро обнаружить и отследить вновь запущенное созвездие. [1]

Импорт спутникового созвездия из файла TLE

Наборы Двухлинейных Элементов являются общим форматом данных для сохранения орбитальной информации спутников. Можно использовать satelliteScenario объект для импорта спутниковых орбит, определенных в файле TLE. По умолчанию импортированные орбиты спутника распространяются с помощью алгоритма распространения SGP4 орбиты, который обеспечивает хорошую точность для объектов LEO. В этом примере эти орбиты обеспечивают основную истину для тестирования способности радиолокационной системы слежения обнаруживать вновь запущенные спутники.

% Create a satellite scenario
satscene = satelliteScenario;
% Add satellites from TLE file.
tleFile = "leoSatelliteConstellation.tle";
constellation = satellite(satscene, tleFile);

Используйте средство просмотра спутникового сценария, чтобы визуализировать созвездие.

play(satscene);

Симуляция синтетических обнаружений и отслеживание созвездия

Моделирование радаров космического наблюдения

Задайте две станции с вентиляторными радиолокационными балками, просматривающими пространство. Вентиляторы прорезают орбиты спутника, чтобы максимизировать количество обнаружений. Радиолокационные станции, расположенные в Северной Америке, образуют забор Восток-Запад.

% First station coordinates in LLA
station1 = [48 -80 0];

% Second station coordinates in LLA
station2 = [50 -117 0];

Каждая станция оборудована радаром, который моделируется с помощью fusionRadarSensor объект. В порядок обнаружения спутников в область значений LEO, радар имеет следующие требования:

  • Обнаружение объекта 10 дБсм на расстоянии до 2000 км

  • Разрешение объектов горизонтально и вертикально с точностью 100 м на области значений 2000 км

  • Имея поле зрения 120 степеней по азимуту и 30 степени по повышению

  • Взгляд в пространство

% Create fan-shaped monostatic radars
fov = [120;40];
radar1 = fusionRadarSensor(1,...
    'UpdateRate',0.1,... 10 sec
    'ScanMode','No scanning',...
    'MountingAngles',[0 90 0],... look up
    'FieldOfView',fov,... degrees
    'ReferenceRange',2000e3,... m
    'RangeLimits',  [0 2000e3], ... m
    'ReferenceRCS', 10,... dBsm
    'HasFalseAlarms',false,...
    'HasNoise', true,...
    'HasElevation',true,...
    'AzimuthResolution',0.03,... degrees
    'ElevationResolution',0.03,... degrees
    'RangeResolution',2000, ... m % accuracy ~= 2000 * 0.05 (m)
    'DetectionCoordinates','Sensor Spherical',...
    'TargetReportFormat','Detections');

radar2 = clone(radar1);
radar2.SensorIndex = 2;

Радиолокационная обработка Цепи

В этом примере выполняются несколько преобразований координат и преобразование осей, чтобы правильно запустить цепь отслеживания радара. Схема ниже иллюстрирует, как входы, заданные выше, преобразуются и передаются в радар.

На первом этапе вы вычисляете каждое положение спутника в местных осях NED радиолокационной станции. Вы достигаете этого путем первого получения положения ECEF наземной станции и преобразования положения и скорости спутника в координаты ECEF. Радиолокационный вход получается путем взятия различий между положением спутника и положением наземной станции и поворота различий в локальные оси NED наземной станции. Смотрите assembleRadarInputs вспомогательная функция для деталей реализации.

На втором этапе вы добавляете необходимую информацию к объекту обнаружения, чтобы трекер мог работать с состоянием ECEF. Вы используете MeasurementParameters свойство в каждом обнаружении объектов для достижения этой цели, как показано на addMeasurementParams вспомогательная функция.

Определение трекера

Радарные модели, которые вы определили выше, выводят обнаружения. Чтобы оценить орбиты спутника, вы используете трекер. Sensor Fusion and Tracking Toolbox™ предоставляет множество мультиобъекта трекеров. В этом примере вы выбираете трекер Joint Probabilistic Data Association (JPDA), потому что он предлагает хороший баланс эффективности отслеживания и вычислительных затрат.

Вам нужно задать фильтр отслеживания для трекера. Можно использовать модель более низкой точности, чем SGP4, например, кеплеровское интегрирование уравнения движения, чтобы отслеживать спутник. Часто отсутствие верности в модели движения целей компенсируется обновлениями измерений и включением технологического шума в фильтр. Вспомогательная функция initKeplerUKF задает фильтр отслеживания.

% Define the tracker
tracker = trackerJPDA('FilterInitializationFcn',@initKeplerUKF,...
    'HasDetectableTrackIDsInput',true,...
    'ClutterDensity',1e-40,...
    'AssignmentThreshold',1e4,...
    'DeletionThreshold',[5 8],...
    'ConfirmationThreshold',[5 8]);

Выполнение симуляции

В оставшейся части этого примера вы проходите по сценарию, чтобы симулировать радиолокационные обнаружения и отслеживать спутники. Этот раздел использует отдельный класс помощника helperScenarioGlobeViewer для визуализации. Можно использовать этот класс помощника для отображения данных датчика и отслеживания с эллипсами неопределенности и показать истинное положение каждого спутника.

globeDisplay = helperScenarioGlobeViewer;

% Define coverage configuration of each radar and visualize it on the globe
ned1 = dcmecef2ned(station1(1), station1(2));
ned2 = dcmecef2ned(station2(1), station2(2));
covcon(1) = coverageConfig(radar1,lla2ecef(station1),quaternion(ned1,'rotmat','frame'));
covcon(2) = coverageConfig(radar2,lla2ecef(station2),quaternion(ned2, 'rotmat','frame'));
plotCoverage(globeDisplay, covcon)

Вы сначала сгенерируете всю историю состояний созвездия за 5 часов. Затем вы симулируете радиолокационные обнаружения и генерируете дорожки в цикле.

satscene.StopTime = satscene.StartTime + hours(5);
satscene.SampleTime = 10;
numSteps = ceil(seconds(satscene.StopTime - satscene.StartTime)/satscene.SampleTime);

% Get constellation positions and velocity over the course of the simulation
plats = repmat(...
    struct('PlatformID',0,'Position',[0 0 0], 'Velocity', [0 0 0]),...
    numSteps, 40);
for i=1:numel(constellation)
    [pos, vel] = states(constellation(i),'CoordinateFrame',"Geographic");
    for j=1:numSteps
        plats(j,i).Position = pos(:,j)';
        plats(j,i).Velocity = vel(:,j)';
        plats(j,i).PlatformID = i;
    end
end

% Initialize tracks and tracks log
confTracks = objectTrack.empty(0,1);
trackLog = cell(1,numSteps);

% Initialize radar plots
radarplt = helperRadarPlot(fov);

% Set random seed for reproducible results
s = rng;
rng(2020);
step = 0;
while step < numSteps
    time = step*satscene.SampleTime;
    step = step + 1;
    
    % Generate detections of the constellation following the radar
    % processing chain
    targets1 = assembleRadarInputs(station1, plats(step,:));
    [dets1,numdets1] = radar1(targets1, time);
    dets1 = addMeasurementParams(dets1,numdets1,station1);
    
    targets2 = assembleRadarInputs(station2, plats(step,:));
    [dets2, numdets2] = radar2(targets2, time);
    dets2 = addMeasurementParams(dets2, numdets2, station2);
    
    detections = [dets1; dets2];
    updateRadarPlots(radarplt,targets1, targets2 ,dets1, dets2)
    
    % Generate and update tracks
    detectableInput = isDetectable(tracker,time, covcon);
    if ~isempty(detections) || isLocked(tracker)
        [confTracks,~,~,info] = tracker(detections,time,detectableInput);
%         confTracks = deleteBadTracks(tracker,confTracks);
    end
    trackLog{step} = confTracks;

    % Update globe display
    updateDisplay(globeDisplay,time,plats(step,:),detections,[],confTracks);
            
end

Рисунок выше показывает орбиты (синие точки) и обнаружения (красные круги) с точки зрения каждого радара.

% Restore previous random seed state
rng(s);
figure;
snap(globeDisplay);

После 5 часов слежения около половины созвездия отслеживается успешно. Поддержание путей с частичным покрытием орбиты является сложной задачей, поскольку спутники могут часто оставаться незамеченными в течение длительных периодов времени в этом строении. В этом примере существует только две радиолокационные станции. Ожидается, что дополнительные станции слежения позволят повысить эффективность слежения. Метрики назначения, которые оценивают эффективность отслеживания путем сравнения между истинными объектами и треками, показаны ниже.

% Show Assignment metrics
truthIdFcn = @(x)[x.PlatformID];

tam = trackAssignmentMetrics('DistanceFunctionFormat','custom',...
    'AssignmentDistanceFcn',@distanceFcn,...
    'DivergenceDistanceFcn',@distanceFcn,...
    'TruthIdentifierFcn',truthIdFcn,...
    'AssignmentThreshold',1000,...
    'DivergenceThreshold',2000);

for i=1:numSteps
    % Extract the tracker and ground truth at the i-th tracker update
    tracks = trackLog{i};
    truths = plats(i,:);
    % For correct truth-track assignment evaluation, the truth is converted
    % to ECEF
    for j=1:numel(truths)
        R = dcmecef2ned(truths(j).Position(1), truths(j).Position(2));
        truths(j).Velocity = truths(j).Velocity * R;
        truths(j).Position = lla2ecef(truths(j).Position);
    end
    % Extract summary of assignment metrics against tracks and truths
    [trackAM,truthAM] = tam(tracks, truths);

end
% Show cumulative metrics for each individual recorded truth object
results = truthMetricsTable(tam);
results(:,{'TruthID','AssociatedTrackID','BreakLength','EstablishmentLength'})
ans=40×4 table
    TruthID    AssociatedTrackID    BreakLength    EstablishmentLength
    _______    _________________    ___________    ___________________

       1               57                5                 232        
       2               46                0                1283        
       3               32                0                 668        
       4               62               12                 492        
       5               22                0                 436        
       6               54                5                 807        
       7               26                0                 513        
       8               31                0                 665        
       9               43                0                1221        
      10               56                0                1500        
      11               49                0                1339        
      12               41                0                1056        
      13              NaN                0                1800        
      14              NaN                0                1800        
      15              NaN                0                1800        
      16              NaN                0                1800        
      ⋮

В таблице выше перечислены 40 спутников в запущенном созвездии и показаны отслеживаемые спутники со связанными идентификаторами дорожек. Идентификатор дорожки значения NaN указывает, что спутник не отслеживается к концу симуляции. Это либо означает, что орбита спутника не прошла через поле зрения одного из двух радаров, либо трек спутника был сброшен. Трекер может сбросить дорожку из-за недостаточного количества начальных обнаружений, что приводит к большой неопределенности в оценке. Альтернативно, трекер может сбросить дорожку, если спутник не будет обнаружен достаточно скоро, так что отсутствие обновлений приведет к расхождению и в конечном счете удалению.

Сводные данные

В этом примере вы научились использовать satelliteScenario объект из Aerospace Toolbox™ для импорта информации об орбите из файлов TLE. Вы распространили спутниковые траектории с помощью SGP4 и визуализировали сценарий с помощью Satellite Scenario Viewer. Вы научились использовать модели радара и трекера из Sensor Fusion and Tracking Toolbox™ для моделирования системы радиолокации космического наблюдения. Построенная система слежения может предсказать предполагаемую орбиту каждого спутника с помощью модели низкой точности.

Вспомогательные функции

initKeplerUKF инициализирует сигма-точечный фильтр Калмана с помощью модели движения Кеплера.

function filter = initKeplerUKF(detection)

radarsphmeas = detection.Measurement;
[x, y, z] = sph2cart(deg2rad(radarsphmeas(1)),deg2rad(radarsphmeas(2)),radarsphmeas(3));
radarcartmeas = [x y z];
Recef2radar = detection.MeasurementParameters.Orientation;
ecefmeas = detection.MeasurementParameters.OriginPosition + radarcartmeas*Recef2radar;
% This is equivalent to:
% Ry90 = [0 0 -1 ; 0 1 0; 1 0 0]; % frame rotation of 90 deg around y axis
% nedmeas(:) = Ry90' * radarcartmeas(:);
% ecefmeas = lla2ecef(lla) +  nedmeas * dcmecef2ned(lla(1),lla(2));
initState = [ecefmeas(1); 0; ecefmeas(2); 0; ecefmeas(3); 0];

sigpos = 2;% m
sigvel = 0.5;% m/s^2

filter = trackingUKF(@keplerorbit,@cvmeas,initState,...
    'StateCovariance', diag(repmat([1000, 10000].^2,1,3)),...
    'ProcessNoise',diag(repmat([sigpos, sigvel].^2,1,3)));

end

function state = keplerorbit(state,dt)
% keplerorbit performs numerical integration to predict the state of
% Keplerian bodies. The state is [x;vx;y;vy;z;vz]

% Runge-Kutta 4th order integration method:
k1 = kepler(state);
k2 = kepler(state + dt*k1/2);
k3 = kepler(state + dt*k2/2);
k4 = kepler(state + dt*k3);

state = state + dt*(k1+2*k2+2*k3+k4)/6;

    function dstate=kepler(state)
        x =state(1,:);
        vx = state(2,:);
        y=state(3,:);
        vy = state(4,:);
        z=state(5,:);
        vz = state(6,:);

        mu = 398600.4405*1e9; % m^3 s^-2
        omega = 7.292115e-5; % rad/s
        
        r = norm([x y z]);
        g = mu/r^2;
        
        % Coordinates are in a non-intertial frame, account for Coriolis
        % and centripetal acceleration
        ax = -g*x/r + 2*omega*vy + omega^2*x;
        ay = -g*y/r - 2*omega*vx + omega^2*y;
        az = -g*z/r;
        dstate = [vx;ax;vy;ay;vz;az];
    end
end

isDetectable используется в примере, чтобы определить, какие дорожки являются обнаруживаемыми в установленный момент времени.

function detectInput = isDetectable(tracker,time,covcon)

if ~isLocked(tracker)
    detectInput = zeros(0,1,'uint32');
    return
end
tracks = tracker.predictTracksToTime('all',time);
if isempty(tracks)
    detectInput = zeros(0,1,'uint32');
else
    alltrackid = [tracks.TrackID];
    isDetectable = zeros(numel(tracks),numel(covcon),'logical');
    for i = 1:numel(tracks)
        track = tracks(i);
        pos_scene = track.State([1 3 5]);
        for j=1:numel(covcon)
            config = covcon(j);
            % rotate position to sensor frame:
            d_scene = pos_scene(:) - config.Position(:);
            scene2sens = rotmat(config.Orientation,'frame');
            d_sens = scene2sens*d_scene(:);
            [az,el] = cart2sph(d_sens(1),d_sens(2),d_sens(3));
            if abs(rad2deg(az)) <= config.FieldOfView(1)/2 && abs(rad2deg(el)) < config.FieldOfView(2)/2
                isDetectable(i,j) = true;
            else
                isDetectable(i,j) = false;
            end
        end
    end
    
    detectInput = alltrackid(any(isDetectable,2))';
end
end

deleteBadTracks используется для удаления дорожек, которые явно различаются. В частности, разнесенными дорожками в этом примере являются дорожки, текущее положение которых упало на поверхность земли, и дорожки, ковариация которых стала слишком большой.

function tracks = deleteBadTracks(tracker,tracks)
% remove divergent tracks:
%   - tracks with covariance > 1e10 (100 km standard deviation)
%   - tracks with estimated position outside of LEO bounds
n = numel(tracks);
toDelete = zeros(1,n,'logical');
for i=1:numel(tracks)
    [pos, cov] = getTrackPositions(tracks(i),[ 1 0 0 0 0 0 ; 0 0 1 0 0 0; 0 0 0 0 1 0]);
    if norm(pos) < 6500*1e3 || norm(pos) > 8500*1e3 || max(cov,[],'all') > 1e10
        deleteTrack(tracker,tracks(i).TrackID);
        toDelete(i) =true;
    end
end
tracks(toDelete) = [];
end

assembleRadarInput используется для построения положений созвездий в каждом радиолокационном каркасе кузова. Это первый шаг, описанный в схеме.

function targets = assembleRadarInputs(station, constellation)
% For each satellite in the constellation, derive its pose with respect to
% the radar frame.
% inputs:
%          - station        :  LLA vector of the radar ground station
%          - constellation  :  Array of structs containing the LLA position
%                              and NED velocity of each satellite
% outputs:
%          - targets        :  Array of structs containing the pose of each
%                              satellite with respect to the radar, expressed in the local
%                              ground radar frame (NED)

% Template structure for the outputs which contains all the field required
% by the radar step method
targetTemplate =  struct( ...
                'PlatformID', 0, ...
                'ClassID', 0, ...
                'Position', zeros(1,3), ...
                'Velocity', zeros(1,3), ...
                'Acceleration', zeros(1,3), ...
                'Orientation', quaternion(1,0,0,0), ...
                'AngularVelocity', zeros(1,3),...
                'Dimensions', struct( ...
                             'Length', 0, ...
                             'Width', 0, ...
                             'Height', 0, ...
                             'OriginOffset', [0 0 0]), ...
                'Signatures', {{rcsSignature}});


% First convert the current satellite pose to ECEF
targetPoses = repmat(targetTemplate, 1, numel(constellation));
for i=1:numel(constellation)
    lla = constellation(i).Position;
    targetPoses(i).Position = lla2ecef(lla);
    vned = constellation(i).Velocity;
    Rned2ecef = dcmecef2ned(lla(1),lla(2))';
    targetPoses(i).Velocity(:) = Rned2ecef*vned(:);
    targetPoses(i).PlatformID = constellation(i).PlatformID;
    % Orientation and angular velocity are left null, assuming satellite to
    % be point targets with a uniform rcs
end

% Then derive the radar pose in ECEF based on the ground station location
Recef2station = dcmecef2ned(station(1), station(2));
radarPose.Orientation = quaternion(Recef2station,'rotmat','frame');
radarPose.Position = lla2ecef(station);
radarPose.Velocity = zeros(1,3);
radarPose.AngularVelocity = zeros(1,3);

% Finally, take the difference and rotate each vector to the ground station
% NED axes
targets = targetPoses;
for i=1: numel(targetPoses)
    thisTgt = targetPoses(i);
    pos = Recef2station*(thisTgt.Position(:) - radarPose.Position(:));
    vel = Recef2station*(thisTgt.Velocity(:) - radarPose.Velocity(:)) - cross(radarPose.AngularVelocity(:),pos(:));
    angVel = thisTgt.AngularVelocity(:) - radarPose.AngularVelocity(:);
    orient = radarPose.Orientation' * thisTgt.Orientation;

    % Store into target structure array
    targets(i).Position(:) = pos;
    targets(i).Velocity(:) = vel;
    targets(i).AngularVelocity(:) = angVel;
    targets(i).Orientation = orient;
end
end

addMeasurementParam реализует шаг 2 в процессе радиолокационной цепи, как описано на схеме.

function dets = addMeasurementParams(dets, numdets, station)
% Add radar station information to the measurement parameters
Recef2station = dcmecef2ned(station(1), station(2));
for i=1:numdets
    dets{i}.MeasurementParameters.OriginPosition = lla2ecef(station);
    dets{i}.MeasurementParameters.IsParentToChild = true; % parent = ecef, child = radar
    dets{i}.MeasurementParameters.Orientation = dets{i}.MeasurementParameters.Orientation' * Recef2station;
end
end

distanceFcn используется с метриками присвоения для вычисления присвоения отслеживания.

function d = distanceFcn(track, truth)

estimate = track.State([1 3 5 2 4 6]);
true = [truth.Position(:) ; truth.Velocity(:)];
cov = track.StateCovariance([1 3 5 2 4 6], [1 3 5 2 4 6]);
d = (estimate - true)' / cov * (estimate - true);
end

Ссылка

[1] Sridharan, Ramaswamy, and Antonio F. Pensa, eds. Перспективы в области космического наблюдения. MIT Press, 2017.