Прежде чем рассказать про выполнение данной задачи, приведу немного теории. Зона радиовидимости - это геометрическое место точек на поверхности Земли, попадающих в круг, ограниченный на сфере заданным расстоянием до подспутниковой точки.
Время связи наземной станции с ИСЗ ограничено временем нахождения ИСЗ в зоне ее радиовидимости (рис. 1). Эта зона определяется длиной дуги АБ, которая зависит от высоты орбиты спутника и минимального угла возвышения антенны наземной станции следящей за ИСЗ в период нахождения его в зоне радиовидимости. Началом зоны видимости считается превышение значения угла места, минимального значения угла начала зоны видимости, которое зависит от высоты наблюдателя над поверхностью Земного эллипсоида.
Время связи наземной станции с ИСЗ ограничено временем нахождения ИСЗ в зоне ее радиовидимости (рис. 1). Эта зона определяется длиной дуги АБ, которая зависит от высоты орбиты спутника и минимального угла возвышения антенны наземной станции следящей за ИСЗ в период нахождения его в зоне радиовидимости. Началом зоны видимости считается превышение значения угла места, минимального значения угла начала зоны видимости, которое зависит от высоты наблюдателя над поверхностью Земного эллипсоида.
Зону радиовидимости можно охарактеризовать следующими событиями:
- время входа в зону;
- время достижения какого-либо параметра;
- время выхода из зоны.
Во время каждого события вычисляются следующие величины:
- дальность между ИСЗ и станцией (в топографической системе координат);
- азимут;
- угол места;
- угол Солнце–КА–НИП, характеризующий фазу освещенности;
- широта и долгота подспутниковой точки;
- высота ИСЗ;
- номер витка и номер суточного витка.
Параметры относительного положения КА и НИП в ТЦСК, связанной с НИП (дальность, азимут, угол места) считаются по следующим формулам:
дальность:азимут:
где:
XspCr, YspCr , ZspCr - координаты и скорости космического аппарата в гринвичской системе координат;
XspCr, YspCr , ZspCr - координаты и скорости космического аппарата в гринвичской системе координат;
XgrSt, YgrSt
, ZgrSt - координаты и скорости измерительного пункта в гринвичской системе координат (скорости НИП в ГСК обычно равны 0);
Расчет условий наблюдения ИСС с наземных средств слежения производится на основе моделирования параметров движения КА и контроля входа в зону видимости каждого из заданных НИП, прохождения параметра и выхода из зоны видимости.
Программная реализация:
Так как при расчете зон радиовидимости необходимо моделирование движения ИСС, для ускорения работы программы было принято решение реализовать ее на Visual C++, а затем обернуть в управляемую библиотеку на С++\CLI.
Зоны видимости вычисляются для определенного набора наземных станций, вначале был реализован класс Groundstation:
class GroundStation { public: GroundStation(unsigned int _numGrSt, double _fi, double _lam, double _hUnderSea, double _hUnderEarth); static GroundStation OneHundred(); static GroundStation TreeHundred(); static GroundStation FiveHundred(); ~GroundStation(); };
В этом классе хранятся данные обо всех станциях слежения, кроме того предусмотрена возможность создания свои станций.
Обертка этого класса в управляемую библиотеку выглядит следующим образом:
#pragma once using namespace System; #include "GroundStation.h" #include "GroundStation.cpp" namespace StandardBallisticInformation { public ref class GroundStations { public: GroundStations(unsigned int _numGrSt, double _fi, double _lam, double _hUnderSea, double _hUnderEarth, String^ _test ); ~GroundStations(); static GroundStations^ OneHundred(); static GroundStations^ TreeHundred (); static GroundStations^ FiveHundred (); private: GroundStation * grSt; };
Как видно из кода, я подключаю два файла .cpp и .h, это связано с тем, что когда используется заголовочный файл из другого проекта, необходимо с ним подключать также и файл его реализации, иначе будет error LINK2019: unresolved external symbol… Второй способ подключить .cpp файл без #include – это добавить его в проект (Add Existing Item).
При реализации класса-оболочки возникла одна проблема перевода из System::String в std::string, покопавшись в интернете, я нашел способ решения:
static const std::string SysToStd(System::String^ _sysStr) { using namespace Runtime::InteropServices; char *v = (char*)(Marshal::StringToHGlobalAnsi(_sysStr).ToPointer()); std::string rezult = std::string(v); Marshal::FreeHGlobal(System::IntPtr((void*)v)); return rezult; }Теперь перейдем непосредственно к расчету условий наблюдения. Для этого был написан класс ZoneRadioVision:
#include "Vector.h" #include <algorithm> #include <iterator> class ZoneRadioVision { public: ZoneRadioVision(); ZoneRadioVision(ZoneRadioVision const& _copy); ~ZoneRadioVision(); ZoneRadioVision & operator = (ZoneRadioVision & _other); vector<zoneradiovision> Calculate(const GroundStation & _grSt, const Vector &_vect, unsigned _numOfCirc, double _gamm1 = 7.0); // вычисляет ЗРВ для заданного кол-ва витков _gamma1 - угол выдачи vector<date_time> GetDatTime(); //getter-ы, потом преобразуются в св-ва vector<double> GetDistance(); vector<double> GetAzimuts(); //---- и другие методы класса...... private: Date_Time *datTimes; //can use vector or list instead of this massives double *distances; double *azimuths; double *cornersOfLocation; double *fis; double *lambdas; double *altitudes; double *cornersOfSun; int sizeOfmassives; unsigned vitok; unsigned nSutCircle; bool visible; void Swap (ZoneRadioVision & _other); // обмен other and this //---- и другие методы класса...... };
По сути класс ZoneRadioVision – представляет набор значений, характеризующих условия наблюдения на одном витке. Его метод Calculate, позволяет вычислить эти характеристики для n витков.
Для записи всех значений, составляющих зону радиовидимости для одного витка, используются динамические массивы, хотя можно было использовать и контейнеры из STL, но и без них тут не обойдется.
Если мы имеем дело с объектами в куче, нам необходимо переопределить деструктор (RAII idiom), конструктор копирования и оператор присваивания:
Для записи всех значений, составляющих зону радиовидимости для одного витка, используются динамические массивы, хотя можно было использовать и контейнеры из STL, но и без них тут не обойдется.
Если мы имеем дело с объектами в куче, нам необходимо переопределить деструктор (RAII idiom), конструктор копирования и оператор присваивания:
ZoneRadioVision::~ZoneRadioVision() { if (this->sizeOfmassives != 0) { delete[] datTimes; delete[] distances; delete[] azimuths; delete[] cornersOfLocation; delete[] fis; delete[] lambdas; delete[] altitudes; delete[] cornersOfSun; } } ZoneRadioVision::ZoneRadioVision(ZoneRadioVision const& _copy) :visible(_copy.visible), vitok(_copy.vitok), sizeOfmassives(_copy.sizeOfmassives), nSutCircle(_copy.nSutCircle) { if (sizeOfmassives != 0) { datTimes = new Date_Time[sizeOfmassives]; distances = new double[sizeOfmassives]; azimuths = new double[sizeOfmassives]; cornersOfLocation = new double[sizeOfmassives]; fis = new double[sizeOfmassives]; lambdas = new double[sizeOfmassives]; altitudes = new double[sizeOfmassives]; cornersOfSun = new double[sizeOfmassives]; stdext::checked_array_iterator'<'date_time'>' chd_dateTime (datTimes, _copy.sizeOfmassives); std::copy(_copy.datTimes, _copy.datTimes + _copy.sizeOfmassives,chd_dateTime); std::copy(_copy.distances, _copy.distances + _copy.sizeOfmassives, stdext::checked_array_iterator'<'double'>' (distances,_copy.sizeOfmassives)); //. . . . . . . . . . . . . . . . . } ZoneRadioVision & ZoneRadioVision::operator= (ZoneRadioVision & _other) { Swap(_other); return *this; } void ZoneRadioVision::Swap(ZoneRadioVision & _other) { std::swap(visible,_other.visible); std::swap(vitok,_other.vitok); std::swap(sizeOfmassives,_other.sizeOfmassives); std::swap(nSutCircle,_other.nSutCircle); //. . . . . . . . . . . . . . . }
Тут используются std::copy для «глубокого» копирования, т.е. в конструкторе копирования уже не копируется только ссылка на первый элемент массива, а создается новый массив. После этого при вызове деструктора происходит корректное освобождение памяти. Однако простое использование std::copy вызывает warning C4996. Для того чтобы гарантировано обеспечить не выход за пределы контейнера при копировании, следует использовать stdext::checked_array_iterator. Также при переопределении оператора присваивания используется функция std::swap (T& a, T& b) для обмена данными между массивами.
Теперь посмотрим на его обертку:
namespace StandardBallisticInformation { public ref class ZoneRadioVisionCLI : IDisposable { public: ZoneRadioVisionCLI(); ~ZoneRadioVisionCLI(); List'<'ZoneRadioVisionCLI^'>'^ Calculate (const GroundStations^ _gr, const BalVector^ _vect, unsigned _numOfCirc, double _gamm1); // вычисляет ЗРВ для заданного кол-ва витков _gamma1 - угол выдачи property List'<'DateTime'>'^ DatTime { List'<;DateTime'>'^ get() {return dateTime;} private: void set(List'<'DateTime'>'^ value) {dateTime = value;} } property List'<'double'>'^ Distances { List'<'double'>'^ get() {return distances;} private: void set (List'<'double'>'^ value) {distances = value;} } //. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . private: ZoneRadioVision * zrv; unsigned circle, nSutCircle; List'<'double'>'^ distances; List'<'double'>'^ azimuts; //. . . . . . . . . . . . . . ZoneRadioVisionCLI^ GetRadioVisions(ZoneRadioVision* _zrv); List'<'double'>'^ PerevodFromVector(vector'<'double'>' _doubleVect); };
Идея была в том, чтобы отобразить динамические массивы Visual C++ в generic коллекции-свойства С++/CLI. В связи с этим интересной мне показалась реализация функции: List<double>^ PerevodFromVector(vector<double> _doubleVect):
List'<'double'>'^ ZoneRadioVisionCLI::PerevodFromVector(vector'<'double'>' _doubleVect) { vector<double> const& vkt = _doubleVect; array<double>^ ret = gcnew array'<double>(vkt.size()); if (vkt.size()) { pin_ptr<double> dest = &ret[0]; std::memcpy(dest, &vkt[0], vkt.size()*sizeof(double)); } return gcnew List<double>(ret); }Тут используется pin_ptr<double> для получения «сырого» указателя на управляемый array, который потом можно передать в неуправляемый код (std::memcpy(dest, &vkt[0], vkt.size()*sizeof(double));)
Полезные ссылки:
1. Спутниковая связь
Добрый день! Хотелось бы получить программную реализацию (архив с проектом) этой задачки (не могу никак собрать нормально на основе вышепоказанной информации). Спасибо!
ОтветитьУдалить