Перенос на новую организацию GONEC
This commit is contained in:
commit
cb76e401de
Binary file not shown.
|
After Width: | Height: | Size: 120 KiB |
|
|
@ -0,0 +1,74 @@
|
|||
//
|
||||
// Created by dd on 06.06.2023.
|
||||
//
|
||||
|
||||
#ifndef DECODERALMANACH_DECODER_H
|
||||
#define DECODERALMANACH_DECODER_H
|
||||
|
||||
#include "stdint.h"
|
||||
#include "vector.h"
|
||||
#include "time.h"
|
||||
#include "stdbool.h"
|
||||
|
||||
typedef struct __attribute__ ((packed)) {
|
||||
uint8_t NKA;
|
||||
uint16_t coil;
|
||||
struct {
|
||||
uint8_t day;
|
||||
uint8_t month;
|
||||
uint8_t year;
|
||||
} date;
|
||||
double equator_time;
|
||||
double semimajor_axis;
|
||||
double eccentricity;
|
||||
double inclination;
|
||||
double periapsis_argument;
|
||||
double assending_node_longitud;
|
||||
double saros;
|
||||
double assending_node_longitude_delta;
|
||||
double periapsis_argument_delta;
|
||||
uint8_t validity_interval;
|
||||
// uint8_t beginDateWTF;
|
||||
// uint8_t validToWTF;
|
||||
} tGonetsAlmanac;
|
||||
|
||||
|
||||
//возвращаемое значение
|
||||
//это количество элемтов в массиве inRange
|
||||
size_t GonetsAlmanac_GetInRangeForInterval(
|
||||
tGonetsAlmanac *alms, //массив альманахов
|
||||
size_t almsCount, //количество элементов в массиве
|
||||
|
||||
vector2 geoLocation, //собственная широта и долгота
|
||||
float rangeDistance, //ограничение по расстоянию до спутника
|
||||
|
||||
//интервал времени в течении которого (полностью от начала и до конца)
|
||||
//спутник должен находиться в зоне видимости
|
||||
time_t begin,
|
||||
time_t end,
|
||||
|
||||
//возвращаемый массив с номерами спутников
|
||||
uint8_t *inRange
|
||||
);
|
||||
|
||||
|
||||
//возвращаемое значение
|
||||
//это количество элемтов в массиве inRange
|
||||
size_t GonetsAlmanac_GetInRangeForMoment(
|
||||
tGonetsAlmanac *alms, //массив альманахов
|
||||
size_t almsCount, //количество элементов в массиве
|
||||
|
||||
vector2 geoLocation, //собственная широта и долгота
|
||||
float rangeDistance, //ограничение по расстоянию до спутника
|
||||
|
||||
time_t moment,//момент времени для которого запрашиваем спутники в зоне видимости
|
||||
|
||||
//возвращаемый массив с номерами спутников
|
||||
uint8_t *inRange
|
||||
);
|
||||
|
||||
float GonetsAlmanac_GetDistanceByAngleDeg(float angleDeg);
|
||||
|
||||
bool GonetsAlmanac_IsValid(tGonetsAlmanac *alms, time_t now);
|
||||
|
||||
#endif //DECODERALMANACH_DECODER_H
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"dep": [
|
||||
{
|
||||
"type": "git",
|
||||
"provider": "GONEC",
|
||||
"repo": "VectorMath"
|
||||
}
|
||||
],
|
||||
"cmake": {
|
||||
"inc_dirs": [
|
||||
"./inc"
|
||||
],
|
||||
"srcs": [
|
||||
"./src/**.c"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,348 @@
|
|||
#include <math.h>
|
||||
#include <vector.h>
|
||||
#include <time.h>
|
||||
#include <stdbool.h>
|
||||
#include <memory.h>
|
||||
#include "GonetsAlmanac.h"
|
||||
|
||||
|
||||
const static double PI = 3.141592653589793238462643383279;
|
||||
const static double PI2 = 6.283185307179586476925286766559;
|
||||
const static double PIdiv2 = 1.570796326794896619231321691639;
|
||||
const static double PI3div2 = 4.712388980384689857693965074919;
|
||||
const static double _180divPi = 57.29577951308232087679815481410;
|
||||
|
||||
|
||||
float RadToDeg(float rad) {
|
||||
return rad * _180divPi;
|
||||
}
|
||||
|
||||
float DegToRad(float grad) {
|
||||
return grad * (float) (PI / 180.0);
|
||||
}
|
||||
|
||||
|
||||
vector3 GeodesicToSpaceA(vector2 vc, int hh) {
|
||||
double E2 = 0.00669438;
|
||||
double EQ = 6378.137;
|
||||
vc.x = DegToRad(vc.x);
|
||||
vc.y = DegToRad(vc.y);
|
||||
|
||||
double sin_fi = sin(vc.x);
|
||||
double cos_fi = cos(vc.x);
|
||||
double n = EQ / pow(1 - E2 * pow(sin_fi, 2), 0.5);
|
||||
vector3 ret;
|
||||
ret.x = (n + hh) * cos_fi * cos(vc.y);
|
||||
ret.y = (n + hh) * cos_fi * sin(vc.y);
|
||||
ret.z = ((1.0 - E2) * n + hh) * sin_fi;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int GetSecond(int y, int m, int d, int h, int mi, int sec) {
|
||||
int ret = 0;
|
||||
if (y < 2000) y = 2000;
|
||||
y -= 2000;
|
||||
ret = (y * 365) + (y / 4) + 1; //при делении сделай целое
|
||||
if (!(y % 4)) ret--;
|
||||
|
||||
|
||||
int i;
|
||||
for (i = 1; i < m; i++) {
|
||||
int kolDay = 31;
|
||||
switch (i) {
|
||||
case 2: {
|
||||
if (y % 4) kolDay = 28;
|
||||
else
|
||||
kolDay = 29;
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
kolDay = 30;
|
||||
break;
|
||||
case 6:
|
||||
kolDay = 30;
|
||||
break;
|
||||
case 9:
|
||||
kolDay = 30;
|
||||
break;
|
||||
case 11:
|
||||
kolDay = 30;
|
||||
break;
|
||||
}
|
||||
ret += kolDay;
|
||||
}
|
||||
ret += (d - 1);
|
||||
ret = ret * 24 * 60 * 60 + h * 60 * 60 + mi * 60 + sec;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
double modfd(double a, double b) {
|
||||
int dm = floor(a / b);
|
||||
return a - (double) (dm * b);
|
||||
|
||||
}
|
||||
|
||||
vector2 GetCoorAlg1(tGonetsAlmanac *station, int sec, int day, int mon, int year) {
|
||||
vector2 vc;
|
||||
vc.x = 0;
|
||||
vc.y = 0;
|
||||
if (station->saros < 2000) return vc;
|
||||
double secTc = GetSecond(year, mon, day, 0, 0, 0) + sec;
|
||||
double secAll =
|
||||
GetSecond(station->date.year + 2000, station->date.month, station->date.day, 0, 0, 0)
|
||||
+ station->equator_time;
|
||||
|
||||
// double secAll= GetSecund(2023, 6, 5, 0, 0, 0) + station.equator_time;
|
||||
|
||||
if (secAll > secTc)
|
||||
return vc;
|
||||
|
||||
double Ttek_Tnu = secTc - secAll;
|
||||
|
||||
if (Ttek_Tnu > 315360000) return vc;
|
||||
// console.debug("2222");
|
||||
|
||||
//////
|
||||
double i = station->inclination;
|
||||
|
||||
double We = 0.00007303;
|
||||
double T_T = Ttek_Tnu;
|
||||
if (T_T >= station->saros) {
|
||||
T_T = modfd(T_T, station->saros);
|
||||
}
|
||||
|
||||
double U = PI2 * T_T;
|
||||
U = U / station->saros;
|
||||
//console.debug(T_T);
|
||||
double S = asin(sin(i) * sin(U));
|
||||
double Dd = 0;
|
||||
if (0 <= U && U <= PIdiv2) {
|
||||
Dd = atan(cos(i) * tan(U));
|
||||
} else if (PIdiv2 < U && U < PI3div2) {
|
||||
Dd = PI + atan(cos(i) * tan(U));
|
||||
|
||||
} else if (PI3div2 < U && U < PI2) {
|
||||
Dd = 2 * PI + atan(cos(i) * tan(U));
|
||||
|
||||
} else if (U == PIdiv2 || U == PI3div2) {
|
||||
Dd = U;
|
||||
}
|
||||
|
||||
double D = (station->assending_node_longitud + Dd - (We * Ttek_Tnu));
|
||||
if (D >= PI2) {
|
||||
D = modfd(D, PI2);
|
||||
}
|
||||
if (D <= -PI2) {
|
||||
D = modfd(D, -PI2);
|
||||
}
|
||||
if (D < -PI) D += PI2;
|
||||
// console.debug(S);
|
||||
// console.debug(D);
|
||||
vc.x = RadToDeg(S);
|
||||
vc.y = RadToDeg(D);
|
||||
// console.debug(vc.fi,"li=",vc.li);
|
||||
return vc;
|
||||
}
|
||||
|
||||
vector3 AlmanacCalc(tGonetsAlmanac *station, struct tm date) {
|
||||
|
||||
vector2 coord = GetCoorAlg1(
|
||||
station,
|
||||
date.tm_sec + date.tm_min * 60 + date.tm_hour * 3600, date.tm_mday,
|
||||
date.tm_mon + 1,
|
||||
date.tm_year
|
||||
);
|
||||
|
||||
vector3 v = GeodesicToSpaceA(coord, 1500);
|
||||
|
||||
// printf("%d coor = %lf %lf v=%lf %lf %lf\n", station.NKA, coord.x, coord.y, v.x, v.y, v.z);
|
||||
return v;
|
||||
}
|
||||
|
||||
static float getTriangleOppositeAngle(float adjacent, float opposite, float angle) {
|
||||
return asinf((opposite / adjacent) * sinf(angle));
|
||||
}
|
||||
|
||||
static float getTriangleOppositeEdge(float adjacentA, float adjacentB, float angle) {
|
||||
return sqrtf(
|
||||
powf(adjacentA, 2) + powf(adjacentB, 2) - 2 * adjacentA * adjacentB * cosf(angle)
|
||||
);
|
||||
}
|
||||
|
||||
static float getTriangleAdjacentEdge(float adjacent, float opposite, float angle) {
|
||||
float oppositeAngle = (float) PI - getTriangleOppositeAngle(adjacent, opposite, angle) - angle;
|
||||
return getTriangleOppositeEdge(adjacent, opposite, oppositeAngle);
|
||||
}
|
||||
|
||||
static float getTriangleAngle(float adjacentA, float adjacentB, float opposite) {
|
||||
return acosf((powf(adjacentA, 2) + powf(adjacentB, 2) - powf(opposite, 2)) / (2 * adjacentA * adjacentB));
|
||||
}
|
||||
|
||||
|
||||
static const float earthRadius = 6378.135f;
|
||||
static const float orbitMax = 8000.f;
|
||||
static const float RAD_90_DEG = 1.5708f;
|
||||
|
||||
|
||||
float GonetsAlmanac_GetDistanceByAngleDeg(float angleDeg) {
|
||||
return getTriangleAdjacentEdge(orbitMax, earthRadius, (float) (DegToRad(angleDeg) + PI / 2));
|
||||
}
|
||||
|
||||
|
||||
//получаем угол между нормалью и вектором предельной дальности
|
||||
static float rangeAngleFromDistance(float distance) {
|
||||
return (float) (PI - getTriangleAngle(earthRadius, distance, orbitMax));
|
||||
}
|
||||
|
||||
bool GonetsAlmanac_InRange(
|
||||
tGonetsAlmanac *alms,
|
||||
vector3 selfPosition,
|
||||
float rangeDistance,
|
||||
float rangeAngle,
|
||||
struct tm ts
|
||||
) {
|
||||
vector3 satPos; //переменная для записи координат спутника
|
||||
satPos = AlmanacCalc(alms, ts); //получили координаты
|
||||
|
||||
vector3 direction = vector3Less(satPos, selfPosition);// получаем вектор направления от спутника до нас
|
||||
float distance = vector3Len(direction); //узнали дистанцию
|
||||
|
||||
if (distance <= rangeDistance) {
|
||||
|
||||
//рассчитали угол мужду нормалью к поверхности и направлением на спутник
|
||||
float angle = vector3Angle(selfPosition, direction);
|
||||
|
||||
// для наглядности при отладке переводим все в градусы, а так они нафиг ненужны
|
||||
// float angleDeg = RadToDeg(angle);
|
||||
// float rangeAngleDeg = RadToDeg(rangeAngle);
|
||||
|
||||
if (angle < rangeAngle) { //проверили подходит ли спутник
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static const time_t time_step = 60;//шаг времени при проходе интервала
|
||||
|
||||
size_t GonetsAlmanac_GetInRangeForInterval(
|
||||
tGonetsAlmanac *alms,
|
||||
size_t almsCount,
|
||||
|
||||
vector2 geoLocation,
|
||||
float rangeDistance,
|
||||
|
||||
time_t begin,
|
||||
time_t end,
|
||||
|
||||
uint8_t *inRange
|
||||
) {
|
||||
float rangeAngle = rangeAngleFromDistance(rangeDistance);
|
||||
vector3 selfPosition = GeodesicToSpaceA(geoLocation, 0);
|
||||
|
||||
bool notInRange[almsCount];
|
||||
memset(notInRange, 0, almsCount);
|
||||
|
||||
struct tm ts;
|
||||
|
||||
// for (time_t timet = begin; timet <= end; timet += time_step) { //цикл по времени от начала интервала до конца
|
||||
// ts = *gmtime(&timet);
|
||||
// ts.tm_year = ts.tm_year - 100 + 2000;
|
||||
//
|
||||
// for (int i = 0; i < almsCount; i++) { //цикл по всем спутникам
|
||||
// if (!GonetsAlmanac_InRange(alms + i, selfPosition, rangeDistance, rangeAngle, ts)) {
|
||||
// notInRange[i] = true;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
//проверка нахождения спутников в начале интервала
|
||||
{
|
||||
ts = *gmtime(&begin);
|
||||
ts.tm_year = ts.tm_year - 100 + 2000;
|
||||
|
||||
for (int i = 0; i < almsCount; i++) { //цикл по всем спутникам
|
||||
if (!GonetsAlmanac_InRange(alms + i, selfPosition, rangeDistance, rangeAngle, ts)) {
|
||||
notInRange[i] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//проверка нахождения спутников в конце интервала
|
||||
{
|
||||
ts = *gmtime(&end);
|
||||
ts.tm_year = ts.tm_year - 100 + 2000;
|
||||
|
||||
for (int i = 0; i < almsCount; i++) { //цикл по всем спутникам
|
||||
if (!GonetsAlmanac_InRange(alms + i, selfPosition, rangeDistance, rangeAngle, ts)) {
|
||||
notInRange[i] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int inRangeCount = 0;
|
||||
for (size_t i = 0; i < almsCount; ++i) {
|
||||
if (!notInRange[i]) {
|
||||
inRange[inRangeCount] = alms[i].NKA;
|
||||
++inRangeCount;
|
||||
}
|
||||
}
|
||||
|
||||
return inRangeCount;
|
||||
}
|
||||
|
||||
|
||||
size_t GonetsAlmanac_GetInRangeForMoment(
|
||||
tGonetsAlmanac *alms,
|
||||
size_t almsCount,
|
||||
|
||||
vector2 geoLocation,
|
||||
float rangeDistance,
|
||||
|
||||
time_t moment,
|
||||
|
||||
uint8_t *inRange
|
||||
) {
|
||||
float rangeAngle = rangeAngleFromDistance(rangeDistance);
|
||||
vector3 selfPosition = GeodesicToSpaceA(geoLocation, 0);
|
||||
|
||||
bool notInRange[almsCount];
|
||||
memset(notInRange, 0, almsCount);
|
||||
|
||||
struct tm ts;
|
||||
|
||||
ts = *gmtime(&moment);
|
||||
ts.tm_year = ts.tm_year - 100 + 2000;// что за магия?
|
||||
|
||||
for (int i = 0; i < almsCount; i++) { //цикл по всем спутникам
|
||||
if (!GonetsAlmanac_InRange(alms + i, selfPosition, rangeDistance, rangeAngle, ts)) {
|
||||
notInRange[i] = true;
|
||||
}
|
||||
}
|
||||
|
||||
int inRangeCount = 0;
|
||||
for (size_t i = 0; i < almsCount; ++i) {
|
||||
if (!notInRange[i]) {
|
||||
inRange[inRangeCount] = alms[i].NKA;
|
||||
++inRangeCount;
|
||||
}
|
||||
}
|
||||
|
||||
return inRangeCount;
|
||||
}
|
||||
|
||||
bool GonetsAlmanac_IsValid(tGonetsAlmanac *alms, time_t now) {
|
||||
struct tm begin = {0};
|
||||
|
||||
begin.tm_year = alms->date.year + 100;
|
||||
begin.tm_mon = alms->date.month - 1;
|
||||
begin.tm_mday = alms->date.day;
|
||||
// begin.tm_gmtoff = 3600;
|
||||
|
||||
time_t begin_ts = mktime(&begin);
|
||||
|
||||
return (begin_ts + (60 * 60 * 24 * alms->validity_interval)) > now;
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
cmake_minimum_required(VERSION 3.17)
|
||||
project(decoderAlmanacTest C)
|
||||
|
||||
set(CMAKE_C_STANDARD 99)
|
||||
|
||||
include(modular.cmake)
|
||||
|
||||
add_executable(decoderAlmanacTest ${SOURCES} test.c)
|
||||
|
||||
target_link_libraries(decoderAlmanacTest m)
|
||||
|
||||
|
||||
|
||||
#cmake_minimum_required(VERSION 3.17)
|
||||
#project(test C)
|
||||
#
|
||||
#set(CMAKE_C_STANDARD 11)
|
||||
#
|
||||
#
|
||||
#add_executable(test ${SOURCES} test.c)
|
||||
Binary file not shown.
Binary file not shown.
|
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"dep": [
|
||||
{
|
||||
"type": "git",
|
||||
"provider": "GONEC",
|
||||
"repo": "ArrayPrint"
|
||||
},
|
||||
{
|
||||
"type": "local",
|
||||
"dir": "../"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1,112 @@
|
|||
//
|
||||
// Created by xemon on 21.06.23.
|
||||
//
|
||||
#include "GonetsAlmanac.h"
|
||||
#include <stdio.h>
|
||||
#include <vector.h>
|
||||
#include "time.h"
|
||||
|
||||
#define TEST_ALMANAC_FILE "curalm(2).dat"
|
||||
//#define TEST_ALMANAC_FILE "../CURALM.DAT"
|
||||
|
||||
|
||||
//double rangeAngle=90-89.65081259507197; //угол конуса
|
||||
double rangeAngle = 40;
|
||||
double rangeDistance = 5117; //дистанция до спутника
|
||||
const RANGEMIN = 5;
|
||||
|
||||
|
||||
size_t load_from_file(tGonetsAlmanac *alms) {
|
||||
size_t countAlmanac = 0;
|
||||
|
||||
// подгружаем альманахи
|
||||
FILE *f = fopen(TEST_ALMANAC_FILE, "r+");
|
||||
fseek(f, 11, SEEK_CUR);
|
||||
tGonetsAlmanac alm;
|
||||
// сделали декодирование (достаточно просто считать их в запакованную структуру)
|
||||
while (!feof(f)) {
|
||||
size_t read = (fread(&alm, sizeof(tGonetsAlmanac), 1, f));
|
||||
////важно чтоб весь альманах целеком был подгружен!!!!
|
||||
if (read) {
|
||||
*alms = alm;
|
||||
++alms;
|
||||
countAlmanac++;
|
||||
}
|
||||
}
|
||||
fclose(f);
|
||||
|
||||
return countAlmanac;
|
||||
}
|
||||
|
||||
void timeCheck(tGonetsAlmanac *alms, int countAlmanac, time_t now) {
|
||||
//вводим начальные данные
|
||||
|
||||
struct tm ts;
|
||||
// time(&now);
|
||||
|
||||
time_t interval_begin = now - 1 * 60;
|
||||
time_t interval_end = now + 1 * 60;
|
||||
// now += 3 * 3600;
|
||||
// ts = *localtime(&now); //текущее время
|
||||
|
||||
// vector3 vectorAlmanac; //переменная для записи координат спутника
|
||||
|
||||
uint8_t inRange[100]; // массив со спутниками внутри конуса
|
||||
int countRange = 0;
|
||||
|
||||
vector2 selfPosition = {52.232f, 41.2322f};//твоя позиция
|
||||
|
||||
|
||||
countRange = GonetsAlmanac_GetInRangeForInterval(
|
||||
// countRange = GonetsAlmanac_GetInRangeForMoment(
|
||||
alms,
|
||||
countAlmanac,
|
||||
|
||||
selfPosition,
|
||||
4000,
|
||||
|
||||
interval_begin,
|
||||
interval_end,
|
||||
// now,
|
||||
|
||||
inRange
|
||||
);
|
||||
|
||||
printf("in range (%i): ", countRange);
|
||||
for (uint8_t *nka = inRange, *end = inRange + countRange; nka < end; ++nka) {
|
||||
printf("%02i ", *nka);
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
}
|
||||
|
||||
int main() {
|
||||
|
||||
tGonetsAlmanac alms[50];
|
||||
|
||||
int countAlmanac = load_from_file(alms);
|
||||
|
||||
printf("alms (%i): ", countAlmanac);
|
||||
for (tGonetsAlmanac *alm = alms, *end = alms + countAlmanac; alm < end; ++alm) {
|
||||
printf("%02i ", alm->NKA);
|
||||
}
|
||||
|
||||
time_t now, end;
|
||||
now = 1687536080;
|
||||
// now = 1686730934;
|
||||
end = now + 3600 * 120;
|
||||
|
||||
printf("\n");
|
||||
if (GonetsAlmanac_IsValid(alms, now)) {
|
||||
printf("valid\n ");
|
||||
} else {
|
||||
printf("expired\n ");
|
||||
}
|
||||
|
||||
|
||||
for (time_t timestamp = now; timestamp < end; timestamp += 60) {
|
||||
timeCheck(alms, countAlmanac, timestamp);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
Loading…
Reference in New Issue