#include #include #include #include #include #include #include "qfits.h" #include "sgdp4h.h" #define LIM 80 #define NMAX 256 #define D2R M_PI/180.0 #define R2D 180.0/M_PI #define XKMPER 6378.135 // Earth radius in km #define XKMPAU 149597879.691 // AU in km #define FLAT (1.0/298.257) #define STDMAG 6.0 #define MMAX 10 long Isat=0; long Isatsel=0; extern double SGDP4_jd0; struct map { double lat,lng; float alt; char observer[32]; int site_id; } m; struct image { char filename[64]; int naxis1,naxis2,naxis3,nframes; float *zavg,*zstd,*zmax,*znum,*zd; double ra0,de0; float x0,y0; float a[3],b[3],xrms,yrms; double mjd; float *dt,exptime; char nfd[32]; int cospar; }; struct sat { long Isat; char state[10]; float mag; double jd; double dx,dy,dz; double x,y,z,vx,vy,vz; double rsun,rearth; double psun,pearth,p,phase; double r,v,ra,de; double azi,alt; double rx,ry; }; struct track { float x0,y0,x1,y1; }; struct image read_fits(char *filename); struct sat apparent_position(double mjd); double modulo(double,double); void obspos_xyz(double,xyz_t *,xyz_t *); void sunpos_xyz(double,xyz_t *); double gmst(double); double dgmst(double); void forward(double ra0,double de0,double ra,double de,double *x,double *y); void reverse(double ra0,double de0,double x,double y,double *ra,double *de); // 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],filename[LIM],*env; env=getenv("ST_DATADIR"); sprintf(filename,"%s/data/sites.txt",env); 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; } // Precess a celestial position void precess(double mjd0,double ra0,double de0,double mjd,double *ra,double *de) { double t0,t; double zeta,z,theta; double a,b,c; // Angles in radians ra0*=D2R; de0*=D2R; // Time in centuries t0=(mjd0-51544.5)/36525.0; t=(mjd-mjd0)/36525.0; // Precession angles zeta=(2306.2181+1.39656*t0-0.000139*t0*t0)*t; zeta+=(0.30188-0.000344*t0)*t*t+0.017998*t*t*t; zeta*=D2R/3600.0; z=(2306.2181+1.39656*t0-0.000139*t0*t0)*t; z+=(1.09468+0.000066*t0)*t*t+0.018203*t*t*t; z*=D2R/3600.0; theta=(2004.3109-0.85330*t0-0.000217*t0*t0)*t; theta+=-(0.42665+0.000217*t0)*t*t-0.041833*t*t*t; theta*=D2R/3600.0; a=cos(de0)*sin(ra0+zeta); b=cos(theta)*cos(de0)*cos(ra0+zeta)-sin(theta)*sin(de0); c=sin(theta)*cos(de0)*cos(ra0+zeta)+cos(theta)*sin(de0); *ra=(atan2(a,b)+z)*R2D; *de=asin(c)*R2D; if (*ra<360.0) *ra+=360.0; if (*ra>360.0) *ra-=360.0; return; } orbit_t find_tle(char *tlefile,struct image img,int satno) { int i; orbit_t orb; struct sat s; int imode,flag,textflag; FILE *fp=NULL; xyz_t satpos,obspos,satvel,sunpos; double mjd,jd,dx,dy,dz; double rx,ry,ra,de,azi,alt,r,t,d; float x[MMAX],y[MMAX],x0,y0; char norad[7],satname[30]; float isch; float rsun,rearth,psun,pearth,p; char filename[128]; double mnan,mnanmin,rmin; // Open TLE file fp=fopen(tlefile,"rb"); if (fp==NULL) fatal_error("File open failed for reading %s\n",tlefile); // Read TLEs if (satno!=0) { read_twoline(fp,satno,&orb); fclose(fp); return orb; } read_twoline(fp,0,&orb); fclose(fp); for (i=0,mnan=0.0;mnan<360.0;mnan+=0.01,i++) { orb.mnan=mnan*D2R; Isat=orb.satno; imode=init_sgdp4(&orb); mjd=img.mjd+0.5*img.exptime/86400.0; // Compute apparent position s=apparent_position(mjd); r=acos(sin(img.de0*D2R)*sin(s.de*D2R)+cos(img.de0*D2R)*cos(s.de*D2R)*cos((img.ra0-s.ra)*D2R))*R2D; if (r<10.0) { forward(img.ra0,img.de0,s.ra,s.de,&s.rx,&s.ry); r=sqrt(s.rx*s.rx+s.ry*s.ry)/3600.0; } if (i==0 || rnframes; dydn=(trk.y1-trk.y0)/(float) img->nframes; // Allocate z=(float *) malloc(sizeof(float)*img->naxis1*img->naxis2); wt=(int *) malloc(sizeof(int)*img->naxis1*img->naxis2); // Set to zero for (i=0;inaxis1*img->naxis2;i++) { z[i]=0.0; wt[i]=0; } // Loop over frames for (l=0;lnframes;l++) { // Offset dx=dxdn*(l-img->nframes/2); dy=dydn*(l-img->nframes/2); // Integer offset di=(int) floor(dx+0.5); dj=(int) floor(dy+0.5); // Set for (i=0;inaxis1;i++) { for (j=0;jnaxis2;j++) { k=i+img->naxis1*j; k0=i+di+img->naxis1*(j+dj); if (i+di>0 && i+dinaxis1 && j+dj>0 && j+djnaxis2) { wt[k]+=1; if (img->znum[k0]==l) z[k]+=img->zmax[k0]; // else // z[k]+=img->zavg[k0]; } } } } // Scale for (i=0;inaxis1*img->naxis2;i++) { if (wt[i]>0) img->zd[i]=z[i]/(float) wt[i]; else img->zd[i]=z[i]; } img->naxis3=5; free(z); free(wt); return; } int main(int argc,char *argv[]) { int i; struct image img; float zmin,zmax,zavg,zstd; float tr[]={-0.5,1.0,0.0,-0.5,0.0,1.0}; float heat_l[] = {0.0, 0.2, 0.4, 0.6, 1.0}; float heat_r[] = {0.0, 0.5, 1.0, 1.0, 1.0}; float heat_g[] = {0.0, 0.0, 0.5, 1.0, 1.0}; float heat_b[] = {0.0, 0.0, 0.0, 0.3, 1.0}; char text[128]; orbit_t orb; float x0,y0,x1,y1; struct track trk; FILE *file; char filename[128]; int satno=0; char *env; // Read image img=read_fits(argv[1]); // Set site get_site(img.cospar); if (argc==5) satno=atoi(argv[4]); // Find closest orbit orb=find_tle(argv[2],img,satno); trk=plot_satellite(orb,img); track_image(&img,trk); for (i=0,zavg=0.0;i-s.psun && s.p-s.pearths.psun) strcpy(s.state,"sunlit"); // Position differences dx=satpos.x-obspos.x; dy=satpos.y-obspos.y; dz=satpos.z-obspos.z; dvx=satvel.x-obsvel.x; dvy=satvel.y-obsvel.y; dvz=satvel.z-obsvel.z; // Celestial position s.r=sqrt(dx*dx+dy*dy+dz*dz); s.v=(dvx*dx+dvy*dy+dvz*dz)/s.r; ra=modulo(atan2(dy,dx)*R2D,360.0); de=asin(dz/s.r)*R2D; // Precess precess(mjd,ra,de,mjd0,&s.ra,&s.de); // Phase s.phase=acos(((obspos.x-satpos.x)*(sunpos.x-satpos.x)+(obspos.y-satpos.y)*(sunpos.y-satpos.y)+(obspos.z-satpos.z)*(sunpos.z-satpos.z))/(rsun*s.r))*R2D; // Magnitude if (strcmp(s.state,"sunlit")==0) s.mag=STDMAG-15.0+5*log10(s.r)-2.5*log10(sin(s.phase*D2R)+(M_PI-s.phase*D2R)*cos(s.phase*D2R)); else s.mag=15; /* // Convert and project if (strcmp(m.orientation,"horizontal")==0) { equatorial2horizontal(mjd,s.ra,s.de,&s.azi,&s.alt); forward(s.azi,s.alt,&s.rx,&s.ry); } else if (strcmp(m.orientation,"equatorial")==0) { forward(s.ra,s.de,&s.rx,&s.ry); } */ return s; } // 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; } // Return x modulo y [0,y) double modulo(double x,double y) { x=fmod(x,y); if (x<0.0) x+=y; return x; } // Observer position void obspos_xyz(double mjd,xyz_t *pos,xyz_t *vel) { double ff,gc,gs,theta,s,dtheta; s=sin(m.lat*D2R); ff=sqrt(1.0-FLAT*(2.0-FLAT)*s*s); gc=1.0/ff+m.alt/XKMPER; gs=(1.0-FLAT)*(1.0-FLAT)/ff+m.alt/XKMPER; theta=gmst(mjd)+m.lng; dtheta=dgmst(mjd)*D2R/86400; pos->x=gc*cos(m.lat*D2R)*cos(theta*D2R)*XKMPER; pos->y=gc*cos(m.lat*D2R)*sin(theta*D2R)*XKMPER; pos->z=gs*sin(m.lat*D2R)*XKMPER; vel->x=-gc*cos(m.lat*D2R)*sin(theta*D2R)*XKMPER*dtheta; vel->y=gc*cos(m.lat*D2R)*cos(theta*D2R)*XKMPER*dtheta; vel->z=0.0; return; } // Solar position void sunpos_xyz(double mjd,xyz_t *pos) { double jd,t,l0,m,e,c,r; double n,s,ecl,ra,de; 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)); de=asin(sin(ecl)*sin(s)); pos->x=r*cos(de)*cos(ra)*XKMPAU; pos->y=r*cos(de)*sin(ra)*XKMPAU; pos->z=r*sin(de)*XKMPAU; return; } // 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; }