#include #include #include #include #include #include #include "cpgplot.h" #include "sgdp4h.h" #define LIM 128 #define NMAX 1024 #define MMAX 28368 #define D2R M_PI/180.0 #define R2D 180.0/M_PI #define XKMPER 6378.135 // Earth radius in km #define FLAT (1.0/298.257) #define XKMPAU 149597879.691 // AU in km long Isat=0; long Isatsel=0; extern double SGDP4_jd0; struct coeff_lr { int nd,nm,nm1,nf; double sa,ca; } clr[60]; struct coeff_b { int nd,nm,nm1,nf; double sa; } cb[60]; struct map { long satno; double l0,b0,h0; double lat,lng; double mjd; float alt,timezone; int length; char orientation[LIM]; char nfd[LIM],tlefile[LIM],observer[32]; char datadir[LIM],tledir[LIM],notamfile[LIM],xyzfile[LIM]; int site_id,notamflag,xyzflag,moonflag,launchsitesflag; int plotfootprint; float w; } m; struct globe { int n; float l[MMAX],b[MMAX],x[MMAX],y[MMAX],z[MMAX]; } glb; struct sat { long Isat; double jd; double dx,dy,dz; double x,y,z,vx,vy,vz; double rsun,rearth; double psun,pearth,p; double r,ra,de; double azi,alt; double rx,ry; double lng,lat; }; void read_globe(void); void plot_globe(void); double nfd2mjd(char *date); double date2mjd(int year,int month,double day); void mjd2date(double mjd,char *date,int length); void usage(); void interactive_usage(); void nfd_now(char *s); void rotate(int axis,float angle,float *x,float *y,float *z); void sunpos_xyz(double mjd,xyz_t *pos,double *ra,double *de); void lunpos_xyz(double mjd,xyz_t *pos,double *ra,double *de); double gmst(double); double dgmst(double); double modulo(double,double); void get_site(int site_id); void ecliptical2equatorial(double l,double b,double *ra,double *de); void plot_launch_sites(void); int fgetline(FILE *file,char *s,int lim); // Initialize setup void initialize_setup(void) { int i; FILE *file; char *env,filename[128]; // Default parameters m.satno=0; m.timezone=0.0; m.length=60; strcpy(m.orientation,"terrestial"); nfd_now(m.nfd); m.mjd=nfd2mjd(m.nfd); m.w=1.2; m.h0=gmst(m.mjd); m.notamflag=0; m.xyzflag=0; m.moonflag=0; m.launchsitesflag=0; m.plotfootprint=1; // Default settings strcpy(m.observer,"Unknown"); m.site_id=0; // Get environment variables env=getenv("ST_DATADIR"); if (env!=NULL) { strcpy(m.datadir,env); } else { printf("ST_DATADIR environment variable not found.\n"); } env=getenv("ST_COSPAR"); if (env!=NULL) { get_site(atoi(env)); } else { printf("ST_COSPAR environment variable not found.\n"); } env=getenv("ST_TLEDIR"); if (env!=NULL) { strcpy(m.tledir,env); } else { printf("ST_TLEDIR environment variable not found.\n"); } // sprintf(m.tlefile,"%s/classfd.tle",m.tledir); strcpy(m.tlefile,""); // Read LR coefficients sprintf(filename,"%s/data/moonLR.dat",m.datadir); file=fopen(filename,"r"); for (i=0;i<60;i++) fscanf(file,"%d %d %d %d %lf %lf",&clr[i].nd,&clr[i].nm,&clr[i].nm1,&clr[i].nf,&clr[i].sa,&clr[i].ca); fclose(file); // Read B coefficients sprintf(filename,"%s/data/moonB.dat",m.datadir); file=fopen(filename,"r"); for (i=0;i<60;i++) fscanf(file,"%d %d %d %d %lf",&cb[i].nd,&cb[i].nm,&cb[i].nm1,&cb[i].nf,&cb[i].sa); fclose(file); return; } // Convert ecliptical into equatorial coordinates void ecliptical2equatorial(double l,double b,double *ra,double *de) { double eps=23.4392911; *ra=modulo(atan2(sin(l*D2R)*cos(eps*D2R)-tan(b*D2R)*sin(eps*D2R),cos(l*D2R))*R2D,360.0); *de=asin(sin(b*D2R)*cos(eps*D2R)+cos(b*D2R)*sin(eps*D2R)*sin(l*D2R))*R2D; return; } void plot_footprint(struct sat s) { int i,j,flag; float range,alpha,dist,zz,theta,rr; float x,y,z,x0,y0,z0,r0,r; // Foot print size range=sqrt(s.x*s.x+s.y*s.y+s.z*s.z); dist=sqrt(range*range-XKMPER*XKMPER); alpha=acos(XKMPER/range); zz=range-dist*sin(alpha); rr=sqrt(XKMPER*XKMPER-zz*zz); // Sub satellite point z=cos(s.lng*D2R)*cos(s.lat*D2R)*XKMPER; x=sin(s.lng*D2R)*cos(s.lat*D2R)*XKMPER; y=sin(s.lat*D2R)*XKMPER; rotate(1,m.l0,&x,&y,&z); rotate(0,m.b0,&x,&y,&z); r=sqrt(x*x+y*y); z0=cos(s.lng*D2R)*cos(s.lat*D2R)*range; x0=sin(s.lng*D2R)*cos(s.lat*D2R)*range; y0=sin(s.lat*D2R)*range; rotate(1,m.l0,&x0,&y0,&z0); rotate(0,m.b0,&x0,&y0,&z0); r0=sqrt(x0*x0+y0*y0); if (rXKMPER || (r00.0)) { cpgmove(x0,y0); cpgdraw(x,y); } if (z>0.0) cpgpt1(x,y,4); for (i=0,j=0,flag=0;i0.0) flag=1; else flag=0; } return; } // Computes apparent position struct sat apparent_position(double mjd) { struct sat s; double jd,rsun,rearth; double dx,dy,dz; xyz_t satpos,obspos,satvel,sunpos; double sra,sde; // Sat ID s.Isat=Isat; // Get Julian Date jd=mjd+2400000.5; // Get positions satpos_xyz(jd,&satpos,&satvel); sunpos_xyz(mjd,&sunpos,&sra,&sde); // Sat positions s.x=satpos.x; s.y=satpos.y; s.z=satpos.z; s.vx=satvel.x; s.vy=satvel.y; s.vz=satvel.y; // Sun position from satellite dx=-satpos.x+sunpos.x; dy=-satpos.y+sunpos.y; dz=-satpos.z+sunpos.z; // Distances rsun=sqrt(dx*dx+dy*dy+dz*dz); rearth=sqrt(satpos.x*satpos.x+satpos.y*satpos.y+satpos.z*satpos.z); // Angles s.psun=asin(696.0e3/rsun)*R2D; s.pearth=asin(6378.135/rearth)*R2D; s.p=acos((-dx*satpos.x-dy*satpos.y-dz*satpos.z)/(rsun*rearth))*R2D; // s.p=acos(((sunpos.x+satpos.x)*satpos.x+(sunpos.y+satpos.y)*satpos.y+(sunpos.z+satpos.z)*satpos.z)/(rsun*rearth))*R2D; s.p-=s.pearth; // Celestial position s.r=sqrt(satpos.x*satpos.x+satpos.y*satpos.y+satpos.z*satpos.z); s.ra=atan2(satpos.y,satpos.x)*R2D; s.de=asin(satpos.z/s.r)*R2D; // Latitude and longitude s.lng=s.ra-gmst(m.mjd);; s.lat=s.de; return s; } // plot satellite track void plot_track(void) { int i=0,nstep=500; orbit_t orb; xyz_t pos,vel; double jd,dt,h,mjd; FILE *fp=NULL; float x,y,z,r,v; long imode; int isci; float isch; char norad[7]; struct sat s; float rmin,rmax; float xmin,ymin,zmin,xmax,ymax,zmax; if (strcmp(m.tlefile,"")==0) return; cpgqci(&isci); cpgqch(&isch); cpgsci(7); fp=fopen(m.tlefile,"rb"); if (fp==NULL) { fatal_error("File open failed for reading \"%s\"",m.tlefile); } while (read_twoline(fp,m.satno,&orb) == 0) { // print_orb(&orb); Isat=orb.satno; imode=init_sgdp4(&orb); if(imode == SGDP4_ERROR) continue; jd=m.mjd+2400000.5; h=gmst(m.mjd); for (i=0,dt=0.0;;i++) { //if(satpos_xyz(jd, &pos, &vel) == SGDP4_ERROR) break; mjd=jd-2400000.5; s=apparent_position(mjd); x=s.x; y=s.y; z=s.z; rotate(0,-90.0,&x,&y,&z); rotate(1,90.0,&x,&y,&z); rotate(1,m.l0+h,&x,&y,&z); rotate(0,m.b0,&x,&y,&z); // Visibility if (s.p<-s.psun) cpgsci(14); else if (s.p>-s.psun && s.ps.psun) cpgsci(7); // Find perigee and apogee if (i==0) { rmin=s.r; rmax=s.r; } else { if (s.rrmax) { rmax=s.r; xmax=x; ymax=y; zmax=z; } } // Plot if (i==0) { if (m.plotfootprint==1) plot_footprint(s); if (!(sqrt(x*x+y*y)XKMPER) { if (sqrt(x*x+y*y)0) { // Get satellite position if (line[10]=='T') { sscanf(line,"%s %lf %lf %lf",nfd,&satpos.x,&satpos.y,&satpos.z); mjd=nfd2mjd(nfd); } else { sscanf(line,"%lf %lf %lf %lf",&mjd,&satpos.x,&satpos.y,&satpos.z); } // Mark point to plot if (mjd>m.mjd && mjd0<=m.mjd && flag==0 && i>0) flag=1; // Get positions sunpos_xyz(m.mjd,&sunpos,&sra,&sde); // Sun position from satellite dx=-satpos.x+sunpos.x; dy=-satpos.y+sunpos.y; dz=-satpos.z+sunpos.z; // Distances rsun=sqrt(dx*dx+dy*dy+dz*dz); rearth=sqrt(satpos.x*satpos.x+satpos.y*satpos.y+satpos.z*satpos.z); // Angles s.psun=asin(696.0e3/rsun)*R2D; s.pearth=asin(6378.135/rearth)*R2D; s.p=acos((-dx*satpos.x-dy*satpos.y-dz*satpos.z)/(rsun*rearth))*R2D; // s.p=acos(((sunpos.x+satpos.x)*satpos.x+(sunpos.y+satpos.y)*satpos.y+(sunpos.z+satpos.z)*satpos.z)/(rsun*rearth))*R2D; s.p-=s.pearth; // Celestial position s.r=sqrt(satpos.x*satpos.x+satpos.y*satpos.y+satpos.z*satpos.z); s.ra=atan2(satpos.y,satpos.x)*R2D; s.de=asin(satpos.z/s.r)*R2D; // Latitude and longitude s.lng=s.ra-gmst(m.mjd);; s.lat=s.de; s.x=satpos.x; s.y=satpos.y; s.z=satpos.z; x=satpos.x; y=satpos.y; z=satpos.z; rotate(0,-90.0,&x,&y,&z); rotate(1,90.0,&x,&y,&z); rotate(1,m.l0+h,&x,&y,&z); rotate(0,m.b0,&x,&y,&z); // Visibility if (s.p<-s.psun) cpgsci(14); else if (s.p>-s.psun && s.ps.psun) cpgsci(7); // Plot if (flag==1) { flag=2; if (m.plotfootprint==1) plot_footprint(s); if (!(sqrt(x*x+y*y)XKMPER) { if (sqrt(x*x+y*y)0.0) { if (flag==0) { cpgmove(x,y); flag=1; } else { cpgdraw(x,y); } } else { flag=0; } } return; } // plot grid void plot_grid(void) { int i,j,flag; float l,b; float x,y,z; for (l=0.0;l<=360.0;l+=30.0) { for (b=-90.0,flag=0;b<=90.0;b+=1.0) { z=cos(l*D2R)*cos(b*D2R)*XKMPER; x=sin(l*D2R)*cos(b*D2R)*XKMPER; y=sin(b*D2R)*XKMPER; rotate(1,m.l0,&x,&y,&z); rotate(0,m.b0,&x,&y,&z); if (flag==0) cpgmove(x,y); else cpgdraw(x,y); if (z>0.0) flag=1; else flag=0; } } for (b=-90.0;b<=90.0;b+=30.0) { for (l=0.0,flag=0;l<=360.0;l+=1.0) { z=cos(l*D2R)*cos(b*D2R)*XKMPER; x=sin(l*D2R)*cos(b*D2R)*XKMPER; y=sin(b*D2R)*XKMPER; rotate(1,m.l0,&x,&y,&z); rotate(0,m.b0,&x,&y,&z); if (flag==0) cpgmove(x,y); else cpgdraw(x,y); if (z>0.0) flag=1; else flag=0; } } return; } // Plot terminator void plot_moon(void) { xyz_t s; float r,h; float l,b,l0,b0; float x0,y0,z0,x,y,z; double lra,lde,dmjd; int isci; char text[8]; cpgqci(&isci); cpgsci(3); // Get positions lunpos_xyz(m.mjd,&s,&lra,&lde); // GMST h=gmst(m.mjd); // Lunar subpoint l0=modulo(lra-h,360.0); b0=lde; if (l0>180.0) l0-=360.0; // Convert z0=cos(l0*D2R)*cos(b0*D2R)*XKMPER; x0=sin(l0*D2R)*cos(b0*D2R)*XKMPER; y0=sin(b0*D2R)*XKMPER; rotate(1,m.l0,&x0,&y0,&z0); rotate(0,m.b0,&x0,&y0,&z0); // Plot sub lunar point if (z0>0.0) cpgpt1(x0,y0,17); // Lunar antipode l0=modulo(lra-h-180,360.0); b0=-lde; if (l0>180.0) l0-=360.0; // Convert z0=cos(l0*D2R)*cos(b0*D2R)*XKMPER; x0=sin(l0*D2R)*cos(b0*D2R)*XKMPER; y0=sin(b0*D2R)*XKMPER; rotate(1,m.l0,&x0,&y0,&z0); rotate(0,m.b0,&x0,&y0,&z0); // Plot antipode if (z0>0.0) cpgpt1(x0,y0,6); // Plot moon z=s.z; x=s.x; y=s.y; rotate(0,-90.0,&x,&y,&z); rotate(1,90.0,&x,&y,&z); rotate(1,m.l0+h,&x,&y,&z); rotate(0,m.b0,&x,&y,&z); cpgcirc(x,y,1737.5); // Plot antipode travel for (dmjd=1.0;dmjd<7.0;dmjd+=1.0) { // Get positions lunpos_xyz(m.mjd+dmjd,&s,&lra,&lde); // GMST h=gmst(m.mjd); // Lunar antipode l0=modulo(lra-h-180,360.0); b0=-lde; if (l0>180.0) l0-=360.0; // Convert z0=cos(l0*D2R)*cos(b0*D2R)*XKMPER; x0=sin(l0*D2R)*cos(b0*D2R)*XKMPER; y0=sin(b0*D2R)*XKMPER; rotate(1,m.l0,&x0,&y0,&z0); rotate(0,m.b0,&x0,&y0,&z0); // Plot antipode if (z0>0.0) { sprintf(text," %.0f",dmjd); cpgpt1(x0,y0,2); cpgtext(x0,y0,text); } } for (dmjd=-6.0;dmjd<0.0;dmjd+=1.0) { // Get positions lunpos_xyz(m.mjd+dmjd,&s,&lra,&lde); // GMST h=gmst(m.mjd); // Lunar antipode l0=modulo(lra-h-180,360.0); b0=-lde; if (l0>180.0) l0-=360.0; // Convert z0=cos(l0*D2R)*cos(b0*D2R)*XKMPER; x0=sin(l0*D2R)*cos(b0*D2R)*XKMPER; y0=sin(b0*D2R)*XKMPER; rotate(1,m.l0,&x0,&y0,&z0); rotate(0,m.b0,&x0,&y0,&z0); // Plot antipode if (z0>0.0) { sprintf(text," %.0f",dmjd); cpgpt1(x0,y0,2); cpgtext(x0,y0,text); } } cpgsci(isci); return; } // Plot terminator void plot_terminator(void) { int i,j,k,flag,j1,j2; double jd; xyz_t s; float r,h; float l,b,l0,b0; float x0,y0,z0; float x,y,z,t0,t1,t2,t; float xx[NMAX],yy[NMAX],zz[NMAX]; float xt[NMAX],yt[NMAX],zt[NMAX]; int isci; double sra,sde; float theta; float ang[]={0.0,-6.0,-12.0,-18.0}; cpgqci(&isci); // Get positions sunpos_xyz(m.mjd,&s,&sra,&sde); // GMST h=gmst(m.mjd); // Solar subpoint l0=modulo(sra-h,360.0); b0=sde; if (l0>180.0) l0-=360.0; // Convert z0=cos(l0*D2R)*cos(b0*D2R)*XKMPER; x0=sin(l0*D2R)*cos(b0*D2R)*XKMPER; y0=sin(b0*D2R)*XKMPER; rotate(1,m.l0,&x0,&y0,&z0); rotate(0,m.b0,&x0,&y0,&z0); t0=atan2(y0,x0)*R2D; // Loop over terminator boundaries for (i=0,j=0,flag=0;i0 && zz[i]*zz[i-1]<0.0) { if (zz[i]>0.0 && zz[i-1]<0.0) { t1=atan2(yy[i],xx[i])*R2D; j1=i; } else { t2=atan2(yy[i],xx[i])*R2D; j2=i; } } } // angles t0=modulo(t0,360); t1=modulo(t1,360); t2=modulo(t2,360); if (t1512) j2++; if (abs(j2-j1)<512) j2--; if (j1>j2) { for (i=0,j=0;i0.0) { cpgsci(7); cpgpt1(x0,y0,17); } // Loop over terminator boundaries for (k=0;k<4;k++) { if (k==0) cpgsci(2); else cpgsci(4); for (i=0,j=0,flag=0;i0.0) flag=1; else flag=0; } } cpgsci(isci); return; } // Read a line of maximum length int lim from file FILE into string s int fgetline(FILE *file,char *s,int lim) { int c,i=0; while (--lim > 0 && (c=fgetc(file)) != EOF && c != '\n') s[i++] = c; if (c == '\t') c=' '; if (c == '\n') s[i++] = c; s[i] = '\0'; return i; } void plot_notam(char *filename) { int i,flag=0; float x,y,z; float l,b,r; char line[LIM]; FILE *file; file=fopen(filename,"r"); while (fgetline(file,line,LIM)>0) { r=0.0; sscanf(line,"%f %f %f",&b,&l,&r); if (strlen(line)<2) { flag=0; continue; } z=cos(l*D2R)*cos(b*D2R)*XKMPER; x=sin(l*D2R)*cos(b*D2R)*XKMPER; y=sin(b*D2R)*XKMPER; rotate(1,m.l0,&x,&y,&z); rotate(0,m.b0,&x,&y,&z); if (z>0.0) { if (flag==0) { cpgmove(x,y); flag=1; } else { cpgdraw(x,y); } } else { flag=0; } } return; } void plot_map(int plotflag) { int redraw=1,status; char text[256]; float x,y,z; char c; for (;;) { if (redraw>0) { // Get present mjd if (m.mjd<0.0) { nfd_now(m.nfd); m.mjd=nfd2mjd(m.nfd); m.h0=gmst(m.mjd); } // Update position if (strcmp(m.orientation,"terrestial")==0) { m.l0=m.lng; m.b0=m.lat; } else if (strcmp(m.orientation,"sidereal")==0) { m.l0=m.lng-gmst(m.mjd)+m.h0; m.b0=m.lat; } cpgscr(0,0.0,0.0,0.0); cpgeras(); // Create window cpgsvp(0.05,0.95,0.05,0.95); cpgwnad(-m.w*XKMPER,m.w*XKMPER,-m.w*XKMPER,m.w*XKMPER); // Set background cpgscr(0,0.0,0.0,0.5); cpgsci(0); cpgwnad(-m.w*XKMPER,m.w*XKMPER,-m.w*XKMPER,m.w*XKMPER); cpgsci(1); cpgscr(0,0.0,0.0,0.0); // Top left string cpgsch(0.8); mjd2date(m.mjd,m.nfd,0); sprintf(text,"%s UTC",m.nfd); cpgmtxt("T",0.6,0.0,0.0,text); // Bottom string sprintf(text,"l: %d s",m.length); cpgmtxt("B",1.0,0.0,0.0,text); cpgsch(1.0); // Plot terminator plot_terminator(); // Plot Grid cpgsls(2); cpgsci(14); plot_grid(); cpgsls(1); cpgsci(1); // Plot globe plot_globe(); cpgsfs(2); cpgcirc(0.0,0.0,XKMPER); cpgpt1(0.0,0.0,2); cpgsci(1); cpgbox("BC",0.,0,"BC",0.,0); // Plot notam if (m.notamflag==1) { cpgsci(3); plot_notam(m.notamfile); cpgsci(1); } // Plot moon if (m.moonflag==1) plot_moon(); // Plot launch sites if (m.launchsitesflag==1) plot_launch_sites(); // Plot track if (m.xyzflag==1) plot_xyz(); else plot_track(); } // Reset redraw redraw=0; if (plotflag==1) { cpgend(); exit(0); } // Get cursor cpgcurs(&x,&y,&c); // Help if (c=='h') { interactive_usage(); continue; } // Redraw if (c=='r') { m.mjd=-1.0; m.length=60; redraw=1; } // Footprint toggle if (c=='f') { if (m.plotfootprint==1) m.plotfootprint=0; else m.plotfootprint=1; redraw=1; } // Moon toggle if (c=='m') { if (m.moonflag==1) m.moonflag=0; else m.moonflag=1; redraw=1; } // Launchsites toggle if (c=='L') { if (m.launchsitesflag==1) m.launchsitesflag=0; else m.launchsitesflag=1; redraw=1; } // Orientation if (c=='o') { if (strcmp(m.orientation,"terrestial")==0) strcpy(m.orientation,"sidereal"); else if (strcmp(m.orientation,"sidereal")==0) strcpy(m.orientation,"terrestial"); redraw=1; } // Recenter if (sqrt(x*x+y*y)') { m.length*=2.0; redraw=1; } if (c=='<') { m.length/=2.0; redraw=1; } if (c==',') { m.mjd-=m.length/86400.0; redraw=1; } if (c=='.') { m.mjd+=m.length/86400.0; redraw=1; } // Integration length if (c=='l') { printf("Enter integration length (s): "); status=scanf("%d",&m.length); redraw=1; } // Exit if (c=='q' || c=='Q') { cpgend(); exit(0); } } return; } int main(int argc,char *argv[]) { int arg=0,plotflag=0; char plottype[128]="/xs"; // Initialize setup initialize_setup(); // Decode options while ((arg=getopt(argc,argv,"t:c:i:s:l:hN:p:mL:B:R:Sqg:"))!=-1) { switch (arg) { case 'g': strcpy(plottype,optarg); plotflag=1; break; case 't': strcpy(m.nfd,optarg); m.mjd=nfd2mjd(m.nfd); break; case 'c': strcpy(m.tlefile,optarg); break; case 's': get_site(atoi(optarg)); break; case 'i': m.satno=atoi(optarg); break; case 'q': m.launchsitesflag=1; break; case 'l': m.length=atoi(optarg); break; case 'N': strcpy(m.notamfile,optarg); m.notamflag=1; break; case 'L': m.lng=atof(optarg); break; case 'B': m.lat=atof(optarg); break; case 'R': m.w=atof(optarg); break; case 'S': strcpy(m.orientation,"sidereal"); break; case 'p': strcpy(m.xyzfile,optarg); m.xyzflag=1; break; case 'm': m.moonflag=1; break; case 'h': usage(); return 0; break; default: usage(); return 0; } } read_globe(); cpgopen(plottype); plot_map(plotflag); cpgend(); return 0; } // Present nfd void nfd_now(char *s) { time_t rawtime; struct tm *ptm; // Get UTC time time(&rawtime); ptm=gmtime(&rawtime); sprintf(s,"%04d-%02d-%02dT%02d:%02d:%02d",ptm->tm_year+1900,ptm->tm_mon+1,ptm->tm_mday,ptm->tm_hour,ptm->tm_min,ptm->tm_sec); return; } // nfd2mjd double nfd2mjd(char *date) { int year,month,day,hour,min,sec; double mjd,dday; sscanf(date,"%04d-%02d-%02dT%02d:%02d:%02d",&year,&month,&day,&hour,&min,&sec); dday=day+hour/24.0+min/1440.0+sec/86400.0; mjd=date2mjd(year,month,dday); return mjd; } void usage() { printf("usage: satorbit -c TLEFILE [-g DEVICE] [-t TIMESTAMP] [-s COSPARID] [-i SATNO]\n"); printf(" [-q] [-p XYZFILE] [-m] [-N NOTAMFILE] [-l LENGTH]\n"); printf(" [-L LNG] [-B LAT] [-R ZOOMSIZE] [-S ORIENTATION] [-h]\n\n"); printf("-c TLEFILE The file containing orbital elements in the form of TLEs, 3 lines per object\n"); printf("-g DEVICE PGPlot device (default: \"/xs\" --> interactive).\n"); printf(" If set exit the program when everything was drawn.\n"); printf(" default: stay in interactive mode\n"); printf("-t TIMESTAMP Timestamp of the map, formatted as YYYY-mm-ddTHH:MM:SS, default: now\n"); printf("-s COSPARID observation site, COSPAR ID of the observation site on which the map is centered optionally\n"); printf("-i SATNO satno of the selected satellite, default: 0 (all satellites in the TLE file)\n"); printf("-q launchsitesflag: If value=1 plot the launch sites as well, default: 0\n"); printf("-p XYZFILE If given, plot xyz instead of track\n"); printf("-m moonflag: If value=1 plot the moon as well\n"); printf("-N NOTAMFILE If given, plot the NOTAM as well\n"); printf("-l LENGTH Integration length in seconds, default: 60\n"); printf("-L LNG map longitude\n"); printf("-B LAT map latitude\n"); printf("-R ZOOMSIZE Initial window size in earth radii, default: 1.2\n"); printf("-S ORIENTATION map orientation: sidereal, default: terrestial\n"); printf("-h Print usage\n"); } void interactive_usage() { printf("r Redraw\n"); printf("f Toggle footprint visibility\n"); printf("m Toggle moon visibility\n"); printf("L Toggle launchsite visibility\n"); printf("o Switch between terrestial and sidereal orientation\n"); printf("c Center map on cursor position\n"); printf("- Zoom out by a factor of 1.2\n"); printf("+/= Zoom in\n"); printf("{ decrease latitude -2\n"); printf("} increase latitude +2\n"); printf("[ decrease longitude -2\n"); printf("] increase longitude +2\n"); printf("< Divide the integration length by a facor of 2\n"); printf("> Multiply the integration length by a facor of 2\n"); printf(", Increase time (+integration_length in seconds /(1 day))\n"); printf(". Roll back the time\n"); printf("l Enter the integration length in seconds\n"); printf("h this interactive help\n"); printf("q/Q Exit\n"); } // Compute Date from Julian Day void mjd2date(double mjd,char *date,int length) { double f,jd,dday; int z,alpha,a,b,c,d,e; int year,month,day,hour,min; float sec,x; jd=mjd+2400000.5; jd+=0.5; z=floor(jd); f=fmod(jd,1.); if (z<2299161) a=z; else { alpha=floor((z-1867216.25)/36524.25); a=z+1+alpha-floor(alpha/4.); } b=a+1524; c=floor((b-122.1)/365.25); d=floor(365.25*c); e=floor((b-d)/30.6001); dday=b-d-floor(30.6001*e)+f; if (e<14) month=e-1; else month=e-13; if (month>2) year=c-4716; else year=c-4715; day=(int) floor(dday); x=24.0*(dday-day); x=3600.*fabs(x); sec=fmod(x,60.); x=(x-sec)/60.; min=fmod(x,60.); x=(x-min)/60.; hour=x; sec=floor(1000.0*sec)/1000.0; if (length==3) sprintf(date,"%04d-%02d-%02dT%02d:%02d:%06.3f",year,month,day,hour,min,sec); else if (length==0) sprintf(date,"%04d-%02d-%02dT%02d:%02d:%02.0f",year,month,day,hour,min,sec); return; } // Compute Julian Day from Date double date2mjd(int year,int month,double day) { int a,b; double jd; if (month<3) { year--; month+=12; } a=floor(year/100.); b=2.-a+floor(a/4.); if (year<1582) b=0; if (year==1582 && month<10) b=0; if (year==1582 && month==10 && day<=4) b=0; jd=floor(365.25*(year+4716))+floor(30.6001*(month+1))+day+b-1524.5; return jd-2400000.5; } // rotate vector void rotate(int axis,float angle,float *x,float *y,float *z) { float xx,yy,zz; float ca,sa; ca=cos(angle*D2R); sa=sin(angle*D2R); if (axis==0) { xx= *x; yy= *y*ca- *z*sa; zz= *z*ca+ *y*sa; } if (axis==1) { xx= *x*ca- *z*sa; yy= *y; zz= *z*ca+ *x*sa; } if (axis==2) { xx= *x*ca- *y*sa; yy= *y*ca+ *x*sa; zz= *z; } *x=xx; *y=yy; *z=zz; return; } // Moon position void lunpos_xyz(double mjd,xyz_t *pos,double *ra,double *de) { int i; double t,t2,t3,t4; double l1,d,m,m1,f,a1,a2,a3,e,ef; double suml,sumb,sumr,arglr,argb; double l,b,r; // Julian Centuries t=(mjd-51544.5)/36525.0; // Powers of t t2=t*t; t3=t2*t; t4=t3*t; // angles l1=modulo(218.3164477+481267.88123421*t-0.0015786*t2+t3/538841.0-t4/65194000.0,360.0)*D2R; d=modulo(297.8501921+445267.1114034*t-0.0018819*t2+t3/545868.0-t4/113065000.0,360.0)*D2R; m=modulo(357.5291092+35999.0502909*t-0.0001536*t2+t3/24490000.0,360.0)*D2R; m1=modulo(134.9633964+477198.8675055*t+0.0087417*t2+t3/69699.0-t4/14712000.0,360.0)*D2R; f=modulo(93.2720950+483202.0175233*t-0.0036539*t2-t3/3526000.0+t4/86331000.0,360.0)*D2R; a1=modulo(119.75+131.849*t,360.0)*D2R; a2=modulo(53.09+479264.290*t,360.0)*D2R; a3=modulo(313.45+481266.484*t,360.0)*D2R; e=1.0-0.002516*t-0.0000074*t2; // Compute sums for (i=0,suml=sumb=sumr=0.0;i<60;i++) { // Arguments arglr=clr[i].nd*d+clr[i].nm*m+clr[i].nm1*m1+clr[i].nf*f; argb=cb[i].nd*d+cb[i].nm*m+cb[i].nm1*m1+cb[i].nf*f; // E multiplication factor if (abs(clr[i].nm)==1) ef=e; else if (abs(clr[i].nm)==2) ef=e*e; else ef=1.0; // Sums suml+=clr[i].sa*sin(arglr)*ef; sumr+=clr[i].ca*cos(arglr)*ef; // E multiplication factor if (abs(cb[i].nm)==1) ef=e; else if (abs(cb[i].nm)==2) ef=e*e; else ef=1.0; // Sums sumb+=cb[i].sa*sin(argb)*ef; } // Additives suml+=3958*sin(a1)+1962*sin(l1-f)+318*sin(a2); sumb+=-2235*sin(l1)+382*sin(a3)+175*sin(a1-f)+175*sin(a1+f)+127*sin(l1-m1)-115*sin(l1+m1); // Ecliptic longitude, latitude and distance l=modulo(l1*R2D+suml/1000000.0,360.0); b=sumb/1000000.0; r=385000.56+sumr/1000.0; // Equatorial ecliptical2equatorial(l,b,ra,de); // Position pos->x=r*cos(*de*D2R)*cos(*ra*D2R); pos->y=r*cos(*de*D2R)*sin(*ra*D2R); pos->z=r*sin(*de*D2R); return; } // Solar position void sunpos_xyz(double mjd,xyz_t *pos,double *ra,double *de) { double jd,t,l0,m,e,c,r; double n,s,ecl; jd=mjd+2400000.5; t=(jd-2451545.0)/36525.0; l0=modulo(280.46646+t*(36000.76983+t*0.0003032),360.0)*D2R; m=modulo(357.52911+t*(35999.05029-t*0.0001537),360.0)*D2R; e=0.016708634+t*(-0.000042037-t*0.0000001267); c=(1.914602+t*(-0.004817-t*0.000014))*sin(m)*D2R; c+=(0.019993-0.000101*t)*sin(2.0*m)*D2R; c+=0.000289*sin(3.0*m)*D2R; r=1.000001018*(1.0-e*e)/(1.0+e*cos(m+c)); n=modulo(125.04-1934.136*t,360.0)*D2R; s=l0+c+(-0.00569-0.00478*sin(n))*D2R; ecl=(23.43929111+(-46.8150*t-0.00059*t*t+0.001813*t*t*t)/3600.0+0.00256*cos(n))*D2R; *ra=atan2(cos(ecl)*sin(s),cos(s))*R2D; *de=asin(sin(ecl)*sin(s))*R2D; pos->x=r*cos(*de*D2R)*cos(*ra*D2R)*XKMPAU; pos->y=r*cos(*de*D2R)*sin(*ra*D2R)*XKMPAU; pos->z=r*sin(*de*D2R)*XKMPAU; return; } // Return x modulo y [0,y) double modulo(double x,double y) { x=fmod(x,y); if (x<0.0) x+=y; return x; } // Greenwich Mean Sidereal Time double gmst(double mjd) { double t,gmst; t=(mjd-51544.5)/36525.0; gmst=modulo(280.46061837+360.98564736629*(mjd-51544.5)+t*t*(0.000387933-t/38710000),360.0); return gmst; } // Greenwich Mean Sidereal Time double dgmst(double mjd) { double t,dgmst; t=(mjd-51544.5)/36525.0; dgmst=360.98564736629+t*(0.000387933-t/38710000); return dgmst; } // Get observing site void get_site(int site_id) { int i=0; char line[LIM]; FILE *file; int id; double lat,lng; float alt; char abbrev[3],observer[64]; char filename[LIM]; sprintf(filename,"%s/data/sites.txt",m.datadir); file=fopen(filename,"r"); if (file==NULL) { printf("File with site information not found!\n"); return; } while (fgets(line,LIM,file)!=NULL) { // Skip if (strstr(line,"#")!=NULL) continue; // Strip newline line[strlen(line)-1]='\0'; // Read data sscanf(line,"%4d %2s %lf %lf %f", &id,abbrev,&lat,&lng,&alt); strcpy(observer,line+38); // Change to km alt/=1000.0; if (id==site_id) { m.lat=lat; m.lng=lng; m.alt=alt; m.site_id=id; strcpy(m.observer,observer); } } fclose(file); return; } // Plot launch sites void plot_launch_sites(void) { int i=0; char line[LIM]; FILE *file; double lat,lng; char site[64],text[8],filename[LIM]; float isch; float x0,y0,z0,l0,b0; cpgqch(&isch); sprintf(filename,"%s/data/launchsites.txt",m.datadir); file=fopen(filename,"r"); if (file==NULL) { printf("File with site information not found!\n"); return; } while (fgets(line,LIM,file)!=NULL) { // Skip if (strstr(line,"#")!=NULL) continue; // Strip newline line[strlen(line)-1]='\0'; // Read data sscanf(line,"%lf %lf", &lat,&lng); strcpy(site,line+21); l0=modulo(lng,360.0); b0=lat; if (l0>180.0) l0-=360.0; // Convert z0=cos(l0*D2R)*cos(b0*D2R)*XKMPER; x0=sin(l0*D2R)*cos(b0*D2R)*XKMPER; y0=sin(b0*D2R)*XKMPER; rotate(1,m.l0,&x0,&y0,&z0); rotate(0,m.b0,&x0,&y0,&z0); // Plot location if (z0>0.0) { cpgsci(2); cpgsch(0.5); cpgpt1(x0,y0,4); cpgtext(x0,y0,site); cpgsci(1); } } fclose(file); cpgsch(isch); return; }