00001 #define ASDSERIES "sdo.lev0_asd_0004"
00002
00003 #define PT_OUT_OF_MEMORY (-1)
00004 #define PT_DRMS_OPEN_FAILED (-2)
00005 #define PT_NO_VALID_TOBS (-3)
00006
00007 typedef struct {
00008 float sat_y0;
00009 float sat_z0;
00010 float sat_rot;
00011 char acs_mode[16];
00012 char acs_eclp[16];
00013 char acs_sunp[16];
00014 char acs_safe[16];
00015 char acs_cgt[16];
00016 char asd_rec[64];
00017 } PTINFO;
00018
00019 static int find_closest(TIME *t, int n, TIME tt)
00020 {
00021 TIME d, dmin = DBL_MAX;
00022 int i, idx = -1;
00023
00024 for (i=0; i<n; ++i) {
00025 d = fabs(tt - t[i]);
00026 if (d < dmin) {
00027 dmin = d; idx = i;
00028 }
00029 }
00030
00031 return idx;
00032 }
00033
00034
00035
00036
00037
00038
00039
00040 static void qrot(const double *q, const double *x0, double *x)
00041 {
00042 double q11,q12,q13,q21,q22,q23,q31,q32,q33;
00043 q11 = 2 * (q[0]*q[0] + q[1]*q[1]) - 1.0;
00044 q12 = 2 * (q[1]*q[2] + q[0]*q[3]);
00045 q13 = 2 * (q[1]*q[3] - q[0]*q[2]);
00046 q21 = 2 * (q[1]*q[2] - q[0]*q[3]);
00047 q22 = 2 * (q[0]*q[0] + q[2]*q[2]) - 1.0;
00048 q23 = 2 * (q[2]*q[3] + q[0]*q[1]);
00049 q31 = 2 * (q[1]*q[3] + q[0]*q[2]);
00050 q32 = 2 * (q[2]*q[3] - q[0]*q[1]);
00051 q33 = 2 * (q[0]*q[0] + q[3]*q[3]) - 1.0;
00052 x[0] = q11*x0[0] + q12*x0[1] + q13*x0[2];
00053 x[1] = q21*x0[0] + q22*x0[1] + q23*x0[2];
00054 x[2] = q31*x0[0] + q32*x0[1] + q33*x0[2];
00055 }
00056
00057
00058
00059
00060
00061 static void qmul(const double *p, const double *q, double *r)
00062 {
00063 r[0] = p[0]*q[0] - p[1]*q[1] - p[2]*q[2] - p[3]*q[3];
00064 r[1] = p[0]*q[1] + p[1]*q[0] + p[2]*q[3] - p[3]*q[2];
00065 r[2] = p[0]*q[2] + p[2]*q[0] + p[3]*q[1] - p[1]*q[3];
00066 r[3] = p[0]*q[3] + p[3]*q[0] + p[1]*q[2] - p[2]*q[1];
00067 }
00068
00069
00070 static void qinv(double *q)
00071 {
00072 q[1] = -q[1]; q[2] = -q[2]; q[3] = -q[3];
00073 }
00074
00075
00076 static double qnorm(double *q)
00077 {
00078 return sqrt(q[0]*q[0]+q[1]*q[1]+q[2]*q[2]+q[3]*q[3]);
00079 }
00080
00081 int get_pointing_info(DRMS_Env_t *drms_env, TIME *tobs, int nobs, PTINFO **ptinfo)
00082 {
00083 PTINFO *p;
00084 DRMS_RecordSet_t *rset;
00085 TIME tstart, tend, t, *tasd;
00086 int *asdidx;
00087 char dsname[256];
00088 int status, nrec, i, j, k, l;
00089
00090 asdidx = (int *) malloc(nobs*sizeof(int));
00091 p = *ptinfo = (PTINFO *) malloc(nobs*sizeof(PTINFO));
00092 if (!p) return PT_OUT_OF_MEMORY;
00093
00094 for (i=0; i<nobs; ++i) {
00095 asdidx[i] = -1;
00096 p[i].sat_y0 = p[i].sat_z0 = p[i].sat_rot = DRMS_MISSING_FLOAT;
00097 p[i].acs_eclp[0] = p[i].acs_sunp[0] = p[i].acs_safe[0] = 0;
00098 p[i].acs_mode[0] = p[i].acs_cgt[0] = p[i].asd_rec[0] = 0;
00099 }
00100
00101 for (k=0; k<nobs; ++k) {
00102 if (tobs[k] > 0) break;
00103 }
00104 if (k == nobs) {
00105 free(asdidx);
00106 free(p);
00107 *ptinfo = 0;
00108 return PT_NO_VALID_TOBS;
00109 }
00110
00111
00112
00113 do {
00114 for (i=k+1; i<nobs; ++i)
00115 if ((tobs[i]-tobs[k]) > 600.0)
00116 break;
00117 l = i-1;
00118 tstart = tobs[k] - 30.0;
00119 tend = tobs[l] + 30.0;
00120 sprintf(dsname, "%s[? PACKET_TIME > %.0f and PACKET_TIME < %.0f ?]", ASDSERIES, tstart, tend);
00121 rset = drms_open_records(drms_env, dsname, &status);
00122 if (!rset || !rset->n || status) {
00123 free(asdidx);
00124 free(p);
00125 *ptinfo = 0;
00126 if (rset) drms_close_records(rset, DRMS_FREE_RECORD);
00127 return PT_DRMS_OPEN_FAILED;
00128 }
00129 nrec = rset->n;
00130 tasd = (TIME *) malloc(nrec*sizeof(TIME));
00131 if (!tasd) return PT_OUT_OF_MEMORY;
00132 for (i=0; i<nrec; ++i)
00133 tasd[i] = drms_getkey_time(rset->records[i], "PACKET_TIME", &status);
00134
00135
00136 for (i=k; i<=l; ++i) {
00137 int done = 0;
00138 int idx;
00139 char *str;
00140 double qbcs[4], qsn[4], qq[4];
00141 double x[3], x0[3] = {1.0,0.0,0.0};
00142 double z[3], z0[3] = {0.0,0.0,1.0};
00143 double tmp;
00144
00145 if (drms_ismissing_time(tobs[i])) continue;
00146 asdidx[i] = idx = find_closest(tasd, nrec, tobs[i]);
00147 if (idx < 0) continue;
00148
00149 for (j=i-1; j>=k; --j)
00150 if (asdidx[i] == asdidx[j]) {
00151 memcpy(&p[i], &p[j], sizeof(PTINFO));
00152 done = 1;
00153 break;
00154 }
00155 if (!done) {
00156 str = drms_getkey_string(rset->records[idx], "ACS_AN_FLAG_CSS_ECLIPSE", &status);
00157 if (str) {
00158 strncpy(p[i].acs_eclp, str, 16);
00159 free(str);
00160 }
00161 str = drms_getkey_string(rset->records[idx], "ACS_AN_FLAG_ACE_INSAFEHOLD", &status);
00162 if (str) {
00163 strncpy(p[i].acs_safe, str, 16);
00164 free(str);
00165 }
00166 str = drms_getkey_string(rset->records[idx], "ACS_AN_FLAG_DSS_SUNPRES", &status);
00167 if (str) {
00168 strncpy(p[i].acs_sunp, str, 16);
00169 free(str);
00170 }
00171 str = drms_getkey_string(rset->records[idx], "ACS_AN_NUM_CGT", &status);
00172 if (str) {
00173 strncpy(p[i].acs_cgt, str, 16);
00174 free(str);
00175 }
00176 str = drms_getkey_string(rset->records[idx], "ACS_AN_ACS_MODE", &status);
00177 if (str) {
00178 strncpy(p[i].acs_mode, str, 16);
00179 free(str);
00180 }
00181 snprintf(p[i].asd_rec, 64, "%s[:#%lld]", ASDSERIES, rset->records[idx]->recnum);
00182
00183 status = 0;
00184 qbcs[0] = drms_getkey_float(rset->records[idx], "ACS_AN_QUAT_GCIFTOBCSF_EST_S", &status);
00185 qbcs[1] = drms_getkey_float(rset->records[idx], "ACS_AN_QUAT_GCIFTOBCSF_EST_X", &status);
00186 qbcs[2] = drms_getkey_float(rset->records[idx], "ACS_AN_QUAT_GCIFTOBCSF_EST_Y", &status);
00187 qbcs[3] = drms_getkey_float(rset->records[idx], "ACS_AN_QUAT_GCIFTOBCSF_EST_Z", &status);
00188 qsn[0] = drms_getkey_float(rset->records[idx], "ACS_AN_QUAT_GCIFTOSNRF_S", &status);
00189 qsn[1] = drms_getkey_float(rset->records[idx], "ACS_AN_QUAT_GCIFTOSNRF_X", &status);
00190 qsn[2] = drms_getkey_float(rset->records[idx], "ACS_AN_QUAT_GCIFTOSNRF_Y", &status);
00191 qsn[3] = drms_getkey_float(rset->records[idx], "ACS_AN_QUAT_GCIFTOSNRF_Z", &status);
00192 if (status) continue;
00193
00194 tmp = qnorm(qbcs);
00195 if (tmp > 1.001 || tmp < 0.999) continue;
00196 tmp = qnorm(qsn);
00197 if (tmp > 1.001 || tmp < 0.999) continue;
00198
00199 qinv(qsn);
00200 qmul(qsn, qbcs, qq);
00201
00202
00203
00204 qrot(qq, x0, x);
00205
00206
00207
00208 qrot(qq,z0,z);
00209
00210 p[i].sat_rot = -atan2(z[1],z[2])*180.0/M_PI;
00211 p[i].sat_y0 = -asin(x[1])*3600.0*180.0/M_PI;
00212 p[i].sat_z0 = asin(x[2])*3600.0*180.0/M_PI;
00213 }
00214 }
00215 drms_close_records(rset, DRMS_FREE_RECORD);
00216 free(tasd);
00217 k = l+1;
00218 } while (k < nobs);
00219
00220 free(asdidx);
00221 return 0;
00222 }