2024-01-11 13:32:49 -05:00
/**********************************************************************
* This file is used for testing random stuff without running the
* whole of SatDump , which comes in handy for debugging individual
* elements before putting them all together in modules . . .
*
* If you are an user , ignore this file which will not be built by
* default , and if you ' re a developper in need of doing stuff here . . .
* Go ahead !
*
* Don ' t judge the code you might see in there ! : )
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# include "logger.h"
2024-02-23 01:22:22 +01:00
2024-03-09 15:38:41 +01:00
# include <fstream>
# include "common/utils.h"
# include <cmath>
# include "common/geodetic/wgs84.h"
# include "common/geodetic/geodetic_coordinates.h"
# include "common/image/image.h"
# include "libs/predict/predict.h"
# include "common/geodetic/ecef_to_eci.h"
int fcs ( uint8_t * data , int len )
{
int i ;
unsigned char c0 = 0 ;
unsigned char c1 = 0 ;
for ( i = 0 ; i < len ; i + + )
{
c0 = c0 + * ( data + i ) ;
c1 = c1 + c0 ;
}
return ( ( long ) ( c0 + c1 ) ) ; /* returns zero if buffer is error-free*/
}
extern " C "
{
void observer_calculate ( const predict_observer_t * observer , double time , const double pos [ 3 ] , const double vel [ 3 ] , struct predict_observation * result ) ;
}
namespace
{
struct vector
{
double x ;
double y ;
double z ;
} ;
// Must already be in radians!
void lla2xyz ( geodetic : : geodetic_coords_t lla , vector & position )
{
// double asq = geodetic::WGS84::a * geodetic::WGS84::a;
double esq = geodetic : : WGS84 : : e * geodetic : : WGS84 : : e ;
double N = geodetic : : WGS84 : : a / sqrt ( 1 - esq * pow ( sin ( lla . lat ) , 2 ) ) ;
position . x = ( N + lla . alt ) * cos ( lla . lat ) * cos ( lla . lon ) ;
position . y = ( N + lla . alt ) * cos ( lla . lat ) * sin ( lla . lon ) ;
position . z = ( ( 1 - esq ) * N + lla . alt ) * sin ( lla . lat ) ;
}
void xyz2lla ( vector position , geodetic : : geodetic_coords_t & lla )
{
double asq = geodetic : : WGS84 : : a * geodetic : : WGS84 : : a ;
double esq = geodetic : : WGS84 : : e * geodetic : : WGS84 : : e ;
double b = sqrt ( asq * ( 1 - esq ) ) ;
double bsq = b * b ;
double ep = sqrt ( ( asq - bsq ) / bsq ) ;
double p = sqrt ( position . x * position . x + position . y * position . y ) ;
double th = atan2 ( geodetic : : WGS84 : : a * position . z , b * p ) ;
double lon = atan2 ( position . y , position . x ) ;
double lat = atan2 ( ( position . z + ep * ep * b * pow ( sin ( th ) , 3 ) ) , ( p - esq * geodetic : : WGS84 : : a * pow ( cos ( th ) , 3 ) ) ) ;
// double N = geodetic::WGS84::a / (sqrt(1 - esq * pow(sin(lat), 2)));
vector g ;
lla2xyz ( geodetic : : geodetic_coords_t ( lat , lon , 0 , true ) , g ) ;
double gm = sqrt ( g . x * g . x + g . y * g . y + g . z * g . z ) ;
double am = sqrt ( position . x * position . x + position . y * position . y + position . z * position . z ) ;
double alt = am - gm ;
lla = geodetic : : geodetic_coords_t ( lat , lon , alt , true ) ;
}
inline float az_el_to_plot_x ( float plot_size , float radius , float az , float el ) { return sin ( az * DEG_TO_RAD ) * plot_size * radius * ( ( 90.0 - el ) / 90.0 ) ; }
inline float az_el_to_plot_y ( float plot_size , float radius , float az , float el ) { return cos ( az * DEG_TO_RAD ) * plot_size * radius * ( ( 90.0 - el ) / 90.0 ) ; }
}
# include "common/repack.h"
double calcFreq ( int f , bool small = true )
{
if ( small )
{
if ( f < = 0x40 )
f = 0x1 < < 8 | f ;
else if ( f > = 0x50 )
f = 0x0 < < 8 | f ;
}
return 137.0 + double ( f ) * 0.0025 ;
}
2024-02-23 01:22:22 +01:00
int main ( int argc , char * argv [ ] )
2024-01-11 13:32:49 -05:00
{
initLogger ( ) ;
completeLoggerInit ( ) ;
2024-03-09 15:38:41 +01:00
std : : ifstream data_in ( argv [ 1 ] , std : : ios : : binary ) ;
2024-02-23 01:22:22 +01:00
2024-03-09 15:38:41 +01:00
uint8_t frm [ 600 ] ;
2024-02-23 01:22:22 +01:00
2024-03-09 15:38:41 +01:00
vector observer_pos ;
2024-02-23 01:22:22 +01:00
2024-03-09 15:38:41 +01:00
int plot_size = 512 ;
image : : Image < uint8_t > img ( plot_size , plot_size , 3 ) ;
// {
// All black bg
img . fill ( 0 ) ;
2024-02-23 01:22:22 +01:00
2024-03-09 15:38:41 +01:00
// Draw the "target-like" plot with elevation rings
float radius = 0.45 ;
float radius1 = plot_size * radius * ( 3.0 / 9.0 ) ;
float radius2 = plot_size * radius * ( 6.0 / 9.0 ) ;
float radius3 = plot_size * radius * ( 9.0 / 9.0 ) ;
2024-02-23 01:22:22 +01:00
2024-03-09 15:38:41 +01:00
uint8_t color_green [ ] = { 0 , 255 , 0 } ;
uint8_t color_red [ ] = { 255 , 0 , 0 } ;
uint8_t color_orange [ ] = { 255 , 165 , 0 } ;
uint8_t color_cyan [ ] = { 0 , 237 , 255 } ;
2024-02-23 01:22:22 +01:00
2024-03-09 15:38:41 +01:00
img . draw_circle ( plot_size / 2 , plot_size / 2 ,
radius1 , color_green , false ) ;
img . draw_circle ( plot_size / 2 , plot_size / 2 ,
radius2 , color_green , false ) ;
img . draw_circle ( plot_size / 2 , plot_size / 2 ,
radius3 , color_green , false ) ;
2024-02-23 15:19:39 +01:00
2024-03-09 15:38:41 +01:00
img . draw_line ( plot_size / 2 , 0 ,
plot_size / 2 , plot_size - 1 ,
color_green ) ;
img . draw_line ( 0 , plot_size / 2 ,
plot_size - 1 , plot_size / 2 ,
color_green ) ;
// }
2024-02-23 01:22:22 +01:00
2024-03-09 15:38:41 +01:00
while ( ! data_in . eof ( ) )
2024-02-23 01:22:22 +01:00
{
2024-03-09 15:38:41 +01:00
data_in . read ( ( char * ) frm , 600 ) ;
for ( int i = 0 ; i < 50 ; i + + )
{
if ( frm [ i * 12 ] = = 0x1F )
{
if ( fcs ( & frm [ i * 12 ] , 24 ) = = 0 )
{
std : : reverse ( & frm [ i * 12 + 2 ] , & frm [ i * 12 + 22 ] ) ;
int scid = frm [ i * 12 + 1 ] ;
int week_number = frm [ i * 12 + 2 ] < < 8 | frm [ i * 12 + 3 ] ;
int time_of_week = frm [ i * 12 + 4 ] < < 16 | frm [ i * 12 + 5 ] < < 8 | frm [ i * 12 + 6 ] ;
// logger->info("Week Number %d, Time Of Week %d", week_number, time_of_week);
const double MAX_R_SAT = 8378155.0 ;
const double VAL_20_BITS = 1048576.0 ;
const double MAX_V_SAT = 7700.0 ;
uint32_t values [ 0 ] ;
repackBytesTo20bits ( & frm [ i * 12 + 7 ] , 15 , values ) ;
long x_raw = values [ 5 ] ;
long y_raw = values [ 4 ] ;
long z_raw = values [ 3 ] ;
long x_raw2 = values [ 2 ] ;
long y_raw2 = values [ 1 ] ;
long z_raw2 = values [ 0 ] ;
double X = ( ( 2.0 * x_raw * MAX_R_SAT ) / VAL_20_BITS - MAX_R_SAT ) / 1000.0 ;
double Y = ( ( 2.0 * y_raw * MAX_R_SAT ) / VAL_20_BITS - MAX_R_SAT ) / 1000.0 ;
double Z = ( ( 2.0 * z_raw * MAX_R_SAT ) / VAL_20_BITS - MAX_R_SAT ) / 1000.0 ;
double X_DOT = ( ( 2.0 * x_raw2 * MAX_V_SAT ) / VAL_20_BITS - MAX_R_SAT ) / 1000.0 ;
double Y_DOT = ( ( 2.0 * y_raw2 * MAX_V_SAT ) / VAL_20_BITS - MAX_R_SAT ) / 1000.0 ;
double Z_DOT = ( ( 2.0 * z_raw2 * MAX_V_SAT ) / VAL_20_BITS - MAX_R_SAT ) / 1000.0 ;
geodetic : : geodetic_coords_t lla ;
xyz2lla ( { X , Y , Z } , lla ) ;
lla . toDegs ( ) ;
// Az/El
double az , el , range , range_rate ;
{
double pos [ 3 ] ;
pos [ 0 ] = X * 1000.0 ;
pos [ 1 ] = Y * 1000.0 ;
pos [ 2 ] = Z * 1000.0 ;
double vel [ 3 ] ;
vel [ 0 ] = X_DOT * 1000.0 ;
vel [ 1 ] = Y_DOT * 1000.0 ;
vel [ 2 ] = Z_DOT * 1000.0 ;
ecef_epehem_to_eci ( 0 , pos [ 0 ] , pos [ 1 ] , pos [ 2 ] , vel [ 0 ] , vel [ 1 ] , vel [ 2 ] ) ;
predict_observation observ ;
observer_calculate ( predict_obs , predict_to_julian ( 0 ) + 2444238.5 , pos , vel , & observ ) ;
az = observ . azimuth * RAD_TO_DEG ;
el = observ . elevation * RAD_TO_DEG ;
range = observ . range ;
}
logger - > info ( " SCID %d, Week Number %d, Time Of Week %d - X %.3d Y %.3d Z %.3d - X %.3f Y %.3f Z %.3f - Lon %.1f, Lat %.1f, Alt %.1f - Az %.1f El %.1f Range %.1f " ,
scid + 70 , week_number , time_of_week ,
x_raw , y_raw , z_raw ,
X_DOT , Y_DOT , Z_DOT ,
lla . lon , lla . lat , lla . alt ,
az , el , range ) ;
// Polar Plot!
// Draw the current satellite position
if ( el > 0 )
{
float point_x = plot_size / 2 ;
float point_y = plot_size / 2 ;
point_x + = az_el_to_plot_x ( plot_size , radius , az , el ) ;
point_y - = az_el_to_plot_y ( plot_size , radius , az , el ) ;
2024-02-23 01:22:22 +01:00
2024-03-09 15:38:41 +01:00
uint8_t color [ 3 ] ;
hsv_to_rgb ( fmod ( scid , 10 ) / 10.0 , 1 , 1 , color ) ;
img . draw_circle ( point_x , point_y , 2 , color , true ) ;
}
}
}
else if ( frm [ i * 12 ] = = 0x65 )
{
if ( fcs ( & frm [ i * 12 ] , 24 ) = = 0 )
{
int f = frm [ i * 12 + 5 ] ;
logger - > info ( " Synchronization, Freq %f Mhz " , calcFreq ( f ) ) ;
}
}
else if ( frm [ i * 12 ] = = 0x1C )
{
if ( fcs ( & frm [ i * 12 ] , 12 ) = = 0 )
{
int pos = frm [ i * 12 + 1 ] & 0xF ;
2024-01-11 13:32:49 -05:00
2024-03-09 15:38:41 +01:00
std : : reverse ( & frm [ i * 12 + 2 ] , & frm [ i * 12 + 10 ] ) ;
shift_array_left ( & frm [ i * 12 + 2 ] , 8 , 4 , & frm [ i * 12 + 2 ] ) ;
uint16_t values [ 5 ] ;
repackBytesTo12bits ( & frm [ i * 12 + 2 ] , 8 , values ) ;
2024-02-23 15:19:39 +01:00
2024-03-09 15:38:41 +01:00
std : : string frequencies = " " ;
for ( int i = 0 ; i < 5 ; i + + )
if ( values [ i ] ! = 0 )
frequencies + = std : : to_string ( calcFreq ( values [ i ] , false ) ) + " Mhz, " ;
logger - > info ( " Channels %d : %s " , pos , frequencies . c_str ( ) ) ;
}
}
}
2024-02-23 01:22:22 +01:00
}
2024-01-11 13:32:49 -05:00
2024-03-09 15:38:41 +01:00
img . save_jpeg ( " orbcomm_plot.jpg " ) ;
2024-01-11 13:32:49 -05:00
}