Satellite Observers Workbench. NOT yet complete, just published for forum posters to \"cherry pick\" pieces of code as requiered as an example.
sgp4sdp4/sgp_in.c@0:0a841b89d614, 2010-10-11 (annotated)
- Committer:
- AjK
- Date:
- Mon Oct 11 10:34:55 2010 +0000
- Revision:
- 0:0a841b89d614
Totally Alpha quality as this project isn\t completed. Just publishing it as it answers many questions asked in the forums
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
AjK | 0:0a841b89d614 | 1 | /* Unit SGP_In */ |
AjK | 0:0a841b89d614 | 2 | /* Author: Dr TS Kelso */ |
AjK | 0:0a841b89d614 | 3 | /* Original Version: 1992 Jun 25 */ |
AjK | 0:0a841b89d614 | 4 | /* Current Revision: 1999 Nov 27 */ |
AjK | 0:0a841b89d614 | 5 | /* Version: 2.10 */ |
AjK | 0:0a841b89d614 | 6 | /* Copyright: 1992-1999, All Rights Reserved */ |
AjK | 0:0a841b89d614 | 7 | |
AjK | 0:0a841b89d614 | 8 | /* Ported to C by N. Kyriazis April 6 2001 */ |
AjK | 0:0a841b89d614 | 9 | |
AjK | 0:0a841b89d614 | 10 | #include "sgp4sdp4.h" |
AjK | 0:0a841b89d614 | 11 | |
AjK | 0:0a841b89d614 | 12 | /* Calculates the checksum mod 10 of a line from a TLE set and */ |
AjK | 0:0a841b89d614 | 13 | /* returns 1 if it compares with checksum in column 68, else 0.*/ |
AjK | 0:0a841b89d614 | 14 | /* tle_set is a character string holding the two lines read */ |
AjK | 0:0a841b89d614 | 15 | /* from a text file containing NASA format Keplerian elements. */ |
AjK | 0:0a841b89d614 | 16 | int |
AjK | 0:0a841b89d614 | 17 | Checksum_Good( char *tle_set ) |
AjK | 0:0a841b89d614 | 18 | { |
AjK | 0:0a841b89d614 | 19 | int i, check_digit, value, checksum = 0; |
AjK | 0:0a841b89d614 | 20 | |
AjK | 0:0a841b89d614 | 21 | for(i = 0; i < 68; i++) |
AjK | 0:0a841b89d614 | 22 | { |
AjK | 0:0a841b89d614 | 23 | if( (tle_set[i] >= '0') && (tle_set[i] <= '9') ) |
AjK | 0:0a841b89d614 | 24 | value = tle_set[i] - '0'; |
AjK | 0:0a841b89d614 | 25 | else if( tle_set[i] == '-' ) |
AjK | 0:0a841b89d614 | 26 | value = 1; |
AjK | 0:0a841b89d614 | 27 | else |
AjK | 0:0a841b89d614 | 28 | value = 0; |
AjK | 0:0a841b89d614 | 29 | |
AjK | 0:0a841b89d614 | 30 | checksum += value; |
AjK | 0:0a841b89d614 | 31 | } /* End for(i = 0; i < 68; i++) */ |
AjK | 0:0a841b89d614 | 32 | |
AjK | 0:0a841b89d614 | 33 | checksum %= 10; |
AjK | 0:0a841b89d614 | 34 | check_digit = tle_set[68] - '0'; |
AjK | 0:0a841b89d614 | 35 | |
AjK | 0:0a841b89d614 | 36 | return( checksum == check_digit ); |
AjK | 0:0a841b89d614 | 37 | } /* Function Checksums_Good */ |
AjK | 0:0a841b89d614 | 38 | |
AjK | 0:0a841b89d614 | 39 | /*------------------------------------------------------------------*/ |
AjK | 0:0a841b89d614 | 40 | |
AjK | 0:0a841b89d614 | 41 | /* Carries out various checks on a TLE set to verify its validity */ |
AjK | 0:0a841b89d614 | 42 | /* tle_set is a character string holding the two lines read */ |
AjK | 0:0a841b89d614 | 43 | /* from a text file containing NASA format Keplerian elements. */ |
AjK | 0:0a841b89d614 | 44 | int |
AjK | 0:0a841b89d614 | 45 | Good_Elements( char *tle_set ) |
AjK | 0:0a841b89d614 | 46 | { |
AjK | 0:0a841b89d614 | 47 | /* Verify checksum of both lines of a TLE set */ |
AjK | 0:0a841b89d614 | 48 | if( !Checksum_Good(&tle_set[0]) || !Checksum_Good(&tle_set[69]) ) |
AjK | 0:0a841b89d614 | 49 | return (0); |
AjK | 0:0a841b89d614 | 50 | /* Check the line number of each line */ |
AjK | 0:0a841b89d614 | 51 | if( (tle_set[0] != '1') || (tle_set[69] != '2') ) |
AjK | 0:0a841b89d614 | 52 | return (0); |
AjK | 0:0a841b89d614 | 53 | /* Verify that Satellite Number is same in both lines */ |
AjK | 0:0a841b89d614 | 54 | if( strncmp( &tle_set[2], &tle_set[71], 5 ) != 0 ) |
AjK | 0:0a841b89d614 | 55 | return (0); |
AjK | 0:0a841b89d614 | 56 | /* Check that various elements are in the right place */ |
AjK | 0:0a841b89d614 | 57 | if( |
AjK | 0:0a841b89d614 | 58 | (tle_set[ 23] != '.') || |
AjK | 0:0a841b89d614 | 59 | (tle_set[ 34] != '.') || |
AjK | 0:0a841b89d614 | 60 | (tle_set[ 80] != '.') || |
AjK | 0:0a841b89d614 | 61 | (tle_set[ 89] != '.') || |
AjK | 0:0a841b89d614 | 62 | (tle_set[106] != '.') || |
AjK | 0:0a841b89d614 | 63 | (tle_set[115] != '.') || |
AjK | 0:0a841b89d614 | 64 | (tle_set[123] != '.') || |
AjK | 0:0a841b89d614 | 65 | (strncmp(&tle_set[61], " 0 ", 3) != 0) |
AjK | 0:0a841b89d614 | 66 | ) |
AjK | 0:0a841b89d614 | 67 | return (0); |
AjK | 0:0a841b89d614 | 68 | |
AjK | 0:0a841b89d614 | 69 | return(1); |
AjK | 0:0a841b89d614 | 70 | } /* Function Good_Elements */ |
AjK | 0:0a841b89d614 | 71 | |
AjK | 0:0a841b89d614 | 72 | /*------------------------------------------------------------------*/ |
AjK | 0:0a841b89d614 | 73 | |
AjK | 0:0a841b89d614 | 74 | /* Converts the strings in a raw two-line element set */ |
AjK | 0:0a841b89d614 | 75 | /* to their intended numerical values. No processing */ |
AjK | 0:0a841b89d614 | 76 | /* of these values is done, e.g. from deg to rads etc. */ |
AjK | 0:0a841b89d614 | 77 | /* This is done in the select_ephemeris() function. */ |
AjK | 0:0a841b89d614 | 78 | void |
AjK | 0:0a841b89d614 | 79 | Convert_Satellite_Data( char *tle_set, tle_t *tle ) |
AjK | 0:0a841b89d614 | 80 | { |
AjK | 0:0a841b89d614 | 81 | char buff[15]; |
AjK | 0:0a841b89d614 | 82 | |
AjK | 0:0a841b89d614 | 83 | /** Decode Card 1 **/ |
AjK | 0:0a841b89d614 | 84 | /* Satellite's catalogue number */ |
AjK | 0:0a841b89d614 | 85 | strncpy( buff, &tle_set[2],5 ); |
AjK | 0:0a841b89d614 | 86 | buff[5] = '\0'; |
AjK | 0:0a841b89d614 | 87 | tle->catnr = atoi(buff); |
AjK | 0:0a841b89d614 | 88 | |
AjK | 0:0a841b89d614 | 89 | /* International Designator for satellite */ |
AjK | 0:0a841b89d614 | 90 | strncpy( tle->idesg, &tle_set[9],8 ); |
AjK | 0:0a841b89d614 | 91 | tle->idesg[8] = '\0'; |
AjK | 0:0a841b89d614 | 92 | |
AjK | 0:0a841b89d614 | 93 | /* Satellite's epoch */ |
AjK | 0:0a841b89d614 | 94 | strncpy( buff, &tle_set[18],14 ); |
AjK | 0:0a841b89d614 | 95 | buff[14] = '\0'; |
AjK | 0:0a841b89d614 | 96 | tle->epoch = atof(buff); |
AjK | 0:0a841b89d614 | 97 | |
AjK | 0:0a841b89d614 | 98 | /* Satellite's First Time Derivative */ |
AjK | 0:0a841b89d614 | 99 | strncpy( buff, &tle_set[33],10 ); |
AjK | 0:0a841b89d614 | 100 | buff[10]='\0'; |
AjK | 0:0a841b89d614 | 101 | tle->xndt2o = atof(buff); |
AjK | 0:0a841b89d614 | 102 | |
AjK | 0:0a841b89d614 | 103 | /* Satellite's Second Time Derivative */ |
AjK | 0:0a841b89d614 | 104 | strncpy( buff, &tle_set[44],1 ); |
AjK | 0:0a841b89d614 | 105 | buff[1] = '.'; |
AjK | 0:0a841b89d614 | 106 | strncpy( &buff[2], &tle_set[45],5 ); |
AjK | 0:0a841b89d614 | 107 | buff[7] = 'E'; |
AjK | 0:0a841b89d614 | 108 | strncpy( &buff[8], &tle_set[50],2 ); |
AjK | 0:0a841b89d614 | 109 | buff[10]='\0'; |
AjK | 0:0a841b89d614 | 110 | tle->xndd6o = atof(buff); |
AjK | 0:0a841b89d614 | 111 | |
AjK | 0:0a841b89d614 | 112 | /* Satellite's bstar drag term */ |
AjK | 0:0a841b89d614 | 113 | strncpy( buff, &tle_set[53],1 ); |
AjK | 0:0a841b89d614 | 114 | buff[1] = '.'; |
AjK | 0:0a841b89d614 | 115 | strncpy( &buff[2], &tle_set[54],5 ); |
AjK | 0:0a841b89d614 | 116 | buff[7] = 'E'; |
AjK | 0:0a841b89d614 | 117 | strncpy( &buff[8], &tle_set[59],2 ); |
AjK | 0:0a841b89d614 | 118 | buff[10]='\0'; |
AjK | 0:0a841b89d614 | 119 | tle->bstar = atof(buff); |
AjK | 0:0a841b89d614 | 120 | |
AjK | 0:0a841b89d614 | 121 | /* Element Number */ |
AjK | 0:0a841b89d614 | 122 | strncpy( buff, &tle_set[64],4 ); |
AjK | 0:0a841b89d614 | 123 | buff[4]='\0'; |
AjK | 0:0a841b89d614 | 124 | tle->elset = atoi(buff); |
AjK | 0:0a841b89d614 | 125 | |
AjK | 0:0a841b89d614 | 126 | /** Decode Card 2 **/ |
AjK | 0:0a841b89d614 | 127 | /* Satellite's Orbital Inclination (degrees) */ |
AjK | 0:0a841b89d614 | 128 | strncpy( buff, &tle_set[77], 8 ); |
AjK | 0:0a841b89d614 | 129 | buff[8]='\0'; |
AjK | 0:0a841b89d614 | 130 | tle->xincl = atof(buff); |
AjK | 0:0a841b89d614 | 131 | |
AjK | 0:0a841b89d614 | 132 | /* Satellite's RAAN (degrees) */ |
AjK | 0:0a841b89d614 | 133 | strncpy( buff, &tle_set[86], 8 ); |
AjK | 0:0a841b89d614 | 134 | buff[8]='\0'; |
AjK | 0:0a841b89d614 | 135 | tle->xnodeo = atof(buff); |
AjK | 0:0a841b89d614 | 136 | |
AjK | 0:0a841b89d614 | 137 | /* Satellite's Orbital Eccentricity */ |
AjK | 0:0a841b89d614 | 138 | buff[0] = '.'; |
AjK | 0:0a841b89d614 | 139 | strncpy( &buff[1], &tle_set[95], 7 ); |
AjK | 0:0a841b89d614 | 140 | buff[8]='\0'; |
AjK | 0:0a841b89d614 | 141 | tle->eo = atof(buff); |
AjK | 0:0a841b89d614 | 142 | |
AjK | 0:0a841b89d614 | 143 | /* Satellite's Argument of Perigee (degrees) */ |
AjK | 0:0a841b89d614 | 144 | strncpy( buff, &tle_set[103], 8 ); |
AjK | 0:0a841b89d614 | 145 | buff[8]='\0'; |
AjK | 0:0a841b89d614 | 146 | tle->omegao = atof(buff); |
AjK | 0:0a841b89d614 | 147 | |
AjK | 0:0a841b89d614 | 148 | /* Satellite's Mean Anomaly of Orbit (degrees) */ |
AjK | 0:0a841b89d614 | 149 | strncpy( buff, &tle_set[112], 8 ); |
AjK | 0:0a841b89d614 | 150 | buff[8]='\0'; |
AjK | 0:0a841b89d614 | 151 | tle->xmo = atof(buff); |
AjK | 0:0a841b89d614 | 152 | |
AjK | 0:0a841b89d614 | 153 | /* Satellite's Mean Motion (rev/day) */ |
AjK | 0:0a841b89d614 | 154 | strncpy( buff, &tle_set[121], 10 ); |
AjK | 0:0a841b89d614 | 155 | buff[10]='\0'; |
AjK | 0:0a841b89d614 | 156 | tle->xno = atof(buff); |
AjK | 0:0a841b89d614 | 157 | |
AjK | 0:0a841b89d614 | 158 | /* Satellite's Revolution number at epoch */ |
AjK | 0:0a841b89d614 | 159 | strncpy( buff, &tle_set[132], 5 ); |
AjK | 0:0a841b89d614 | 160 | buff[5]='\0'; |
AjK | 0:0a841b89d614 | 161 | tle->revnum = atof(buff); |
AjK | 0:0a841b89d614 | 162 | |
AjK | 0:0a841b89d614 | 163 | } /* Procedure Convert_Satellite_Data */ |
AjK | 0:0a841b89d614 | 164 | |
AjK | 0:0a841b89d614 | 165 | /*------------------------------------------------------------------*/ |
AjK | 0:0a841b89d614 | 166 | |
AjK | 0:0a841b89d614 | 167 | int |
AjK | 0:0a841b89d614 | 168 | Get_Next_Tle_Set( char line[3][80], tle_t *tle) |
AjK | 0:0a841b89d614 | 169 | { |
AjK | 0:0a841b89d614 | 170 | int idx, /* Index for loops and arrays */ |
AjK | 0:0a841b89d614 | 171 | chr; /* Used for inputting characters */ |
AjK | 0:0a841b89d614 | 172 | |
AjK | 0:0a841b89d614 | 173 | char tle_set[139]; /* Two lines of a TLE set */ |
AjK | 0:0a841b89d614 | 174 | |
AjK | 0:0a841b89d614 | 175 | /* Read the satellite's name */ |
AjK | 0:0a841b89d614 | 176 | for (idx = 0 ; idx < 25; idx++) |
AjK | 0:0a841b89d614 | 177 | { |
AjK | 0:0a841b89d614 | 178 | if( ((chr = line[0][idx]) != CR) && (chr != LF) && (chr != '\0')) |
AjK | 0:0a841b89d614 | 179 | tle->sat_name[idx] = chr; |
AjK | 0:0a841b89d614 | 180 | else |
AjK | 0:0a841b89d614 | 181 | { |
AjK | 0:0a841b89d614 | 182 | /* strip off trailing spaces */ |
AjK | 0:0a841b89d614 | 183 | while ((chr = line[0][--idx]) == ' '); |
AjK | 0:0a841b89d614 | 184 | tle->sat_name[++idx] = '\0'; |
AjK | 0:0a841b89d614 | 185 | break; |
AjK | 0:0a841b89d614 | 186 | } |
AjK | 0:0a841b89d614 | 187 | } |
AjK | 0:0a841b89d614 | 188 | |
AjK | 0:0a841b89d614 | 189 | /* Read in first line of TLE set */ |
AjK | 0:0a841b89d614 | 190 | strncpy(tle_set, line[1], 70); |
AjK | 0:0a841b89d614 | 191 | |
AjK | 0:0a841b89d614 | 192 | /* Read in second line of TLE set and terminate string */ |
AjK | 0:0a841b89d614 | 193 | strncpy(&tle_set[69], line[2], 70); |
AjK | 0:0a841b89d614 | 194 | tle_set[138]='\0'; |
AjK | 0:0a841b89d614 | 195 | |
AjK | 0:0a841b89d614 | 196 | /* Check TLE set and abort if not valid */ |
AjK | 0:0a841b89d614 | 197 | if( !Good_Elements(tle_set) ) |
AjK | 0:0a841b89d614 | 198 | return(-2); |
AjK | 0:0a841b89d614 | 199 | |
AjK | 0:0a841b89d614 | 200 | /* Convert the TLE set to orbital elements */ |
AjK | 0:0a841b89d614 | 201 | Convert_Satellite_Data( tle_set, tle ); |
AjK | 0:0a841b89d614 | 202 | |
AjK | 0:0a841b89d614 | 203 | return(1); |
AjK | 0:0a841b89d614 | 204 | } |
AjK | 0:0a841b89d614 | 205 | |
AjK | 0:0a841b89d614 | 206 | /*------------------------------------------------------------------*/ |
AjK | 0:0a841b89d614 | 207 | |
AjK | 0:0a841b89d614 | 208 | /* Selects the apropriate ephemeris type to be used */ |
AjK | 0:0a841b89d614 | 209 | /* for predictions according to the data in the TLE */ |
AjK | 0:0a841b89d614 | 210 | /* It also processes values in the tle set so that */ |
AjK | 0:0a841b89d614 | 211 | /* they are apropriate for the sgp4/sdp4 routines */ |
AjK | 0:0a841b89d614 | 212 | void |
AjK | 0:0a841b89d614 | 213 | select_ephemeris(tle_t *tle) |
AjK | 0:0a841b89d614 | 214 | { |
AjK | 0:0a841b89d614 | 215 | double ao,xnodp,dd1,dd2,delo,temp,a1,del1,r1; |
AjK | 0:0a841b89d614 | 216 | |
AjK | 0:0a841b89d614 | 217 | /* Preprocess tle set */ |
AjK | 0:0a841b89d614 | 218 | tle->xnodeo *= de2ra; |
AjK | 0:0a841b89d614 | 219 | tle-> omegao *= de2ra; |
AjK | 0:0a841b89d614 | 220 | tle->xmo *= de2ra; |
AjK | 0:0a841b89d614 | 221 | tle->xincl *= de2ra; |
AjK | 0:0a841b89d614 | 222 | temp = twopi/xmnpda/xmnpda; |
AjK | 0:0a841b89d614 | 223 | tle->xno = tle->xno*temp*xmnpda; |
AjK | 0:0a841b89d614 | 224 | tle->xndt2o *= temp; |
AjK | 0:0a841b89d614 | 225 | tle->xndd6o = tle->xndd6o*temp/xmnpda; |
AjK | 0:0a841b89d614 | 226 | tle->bstar /= ae; |
AjK | 0:0a841b89d614 | 227 | |
AjK | 0:0a841b89d614 | 228 | /* Period > 225 minutes is deep space */ |
AjK | 0:0a841b89d614 | 229 | dd1 = (xke/tle->xno); |
AjK | 0:0a841b89d614 | 230 | dd2 = tothrd; |
AjK | 0:0a841b89d614 | 231 | a1 = pow(dd1, dd2); |
AjK | 0:0a841b89d614 | 232 | r1 = cos(tle->xincl); |
AjK | 0:0a841b89d614 | 233 | dd1 = (1.0-tle->eo*tle->eo); |
AjK | 0:0a841b89d614 | 234 | temp = ck2*1.5f*(r1*r1*3.0-1.0)/pow(dd1, 1.5); |
AjK | 0:0a841b89d614 | 235 | del1 = temp/(a1*a1); |
AjK | 0:0a841b89d614 | 236 | ao = a1*(1.0-del1*(tothrd*.5+del1* |
AjK | 0:0a841b89d614 | 237 | (del1*1.654320987654321+1.0))); |
AjK | 0:0a841b89d614 | 238 | delo = temp/(ao*ao); |
AjK | 0:0a841b89d614 | 239 | xnodp = tle->xno/(delo+1.0); |
AjK | 0:0a841b89d614 | 240 | |
AjK | 0:0a841b89d614 | 241 | /* Select a deep-space/near-earth ephemeris */ |
AjK | 0:0a841b89d614 | 242 | if (twopi/xnodp/xmnpda >= .15625) |
AjK | 0:0a841b89d614 | 243 | SetFlag(DEEP_SPACE_EPHEM_FLAG); |
AjK | 0:0a841b89d614 | 244 | else |
AjK | 0:0a841b89d614 | 245 | ClearFlag(DEEP_SPACE_EPHEM_FLAG); |
AjK | 0:0a841b89d614 | 246 | |
AjK | 0:0a841b89d614 | 247 | return; |
AjK | 0:0a841b89d614 | 248 | } /* End of select_ephemeris() */ |
AjK | 0:0a841b89d614 | 249 | |
AjK | 0:0a841b89d614 | 250 | /*------------------------------------------------------------------*/ |
AjK | 0:0a841b89d614 | 251 |