5 #include <gsl/gsl_blas.h>
6 #include <gsl/gsl_linalg.h>
7 #include <gsl/gsl_matrix_double.h>
13 #define VERSION "0.772"
39 int main(
int argc,
char *argv[]) {
43 cout <<
"geolocate_hawkeye " <<
VERSION <<
" ("
44 << __DATE__ <<
" " << __TIME__ <<
")" << endl;
48 <<
"geolocate_hawkeye input_l1a_filename output_geo_filename" << endl;
51 }
else if (argc == 2) {
52 l1a_name.assign(argv[1]);
53 string str_L1A(
"L1A");
54 size_t L1A_found = l1a_name.find(str_L1A);
55 if ((L1A_found == string::npos)) {
56 geo_name.assign(l1a_name+
".GEO");
59 geo_name.replace(L1A_found,str_L1A.length(),
"GEO");
62 l1a_name.assign(argv[1]);
63 geo_name.assign(argv[2]);
67 int grpid, varid, dimid;
68 int dimids[NC_MAX_VAR_DIMS];
74 size_t n_att_rec, n_orb_rec, sdim, pdim, t_len;
76 float rolloff, timeoff;
78 enum l1a_grps { scan_attr,
82 enum geo_grps { scan_attr_geo,
86 status = nc_open(l1a_name.c_str(), NC_NOWRITE, &l1a_ncid);
89 status = nc_inq_grps(l1a_ncid, &l1a_ngrps, l1a_gid);
93 status = nc_inq_dimid(l1a_ncid,
"number_of_pixels", &dimid);
95 nc_inq_dimlen(l1a_ncid, dimid, &pdim);
100 status = nc_inq_varid(grpid,
"att_time", &varid);
102 nc_inq_vardimid(grpid, varid, dimids);
103 nc_inq_dimlen(l1a_ncid, dimids[0], &n_att_rec);
105 double *att_time =
new double[n_att_rec]();
106 status = nc_get_var_double(grpid, varid, att_time);
110 status = nc_inq_varid(grpid,
"att_quat", &varid);
114 status = nc_get_var_float(grpid, varid, &att_quat[0][0]);
118 status = nc_inq_varid(grpid,
"orb_time", &varid);
120 nc_inq_vardimid(grpid, varid, dimids);
121 nc_inq_dimlen(l1a_ncid, dimids[0], &n_orb_rec);
123 double *orb_time =
new double[n_orb_rec]();
124 status = nc_get_var_double(grpid, varid, orb_time);
128 status = nc_inq_varid(grpid,
"orb_pos", &varid);
132 status = nc_get_var_float(grpid, varid, &orb_pos[0][0]);
136 status = nc_inq_varid(grpid,
"orb_vel", &varid);
140 status = nc_get_var_float(grpid, varid, &orb_vel[0][0]);
144 status = nc_inq_att(grpid, NC_GLOBAL,
"roll_offset", &t_type, &t_len);
148 status = nc_get_att_float(grpid, NC_GLOBAL,
"roll_offset", &rolloff);
150 cout <<
"roll_offset=" <<rolloff << endl;
152 status = nc_inq_att(grpid, NC_GLOBAL,
"time_offset", &t_type, &t_len);
156 status = nc_get_att_float(grpid, NC_GLOBAL,
"time_offset", &timeoff);
158 cout <<
"time_offset=" <<timeoff << endl;
161 grpid = l1a_gid[scan_attr];
162 status = nc_inq_varid(grpid,
"scan_time", &varid);
164 nc_inq_vardimid(grpid, varid, dimids);
165 nc_inq_dimlen(l1a_ncid, dimids[0], &sdim);
167 double *stime =
new double[sdim]();
168 status = nc_get_var_double(grpid, varid, stime);
172 char tstart[25] =
"";
174 status = nc_get_att_text(l1a_ncid, NC_GLOBAL,
"time_coverage_start", tstart);
177 status = nc_get_att_text(l1a_ncid, NC_GLOBAL,
"time_coverage_end", tend);
188 double omegae = 7.29211585494e-5;
192 for (
size_t i = 0;
i < n_orb_rec;
i++) {
195 for (
size_t j = 0;
j < 3;
j++) {
196 posr[
i][
j] = ecmat[
j][0] * orb_pos[
i][0] +
197 ecmat[
j][1] * orb_pos[
i][1] +
198 ecmat[
j][2] * orb_pos[
i][2];
199 velr[
i][
j] = ecmat[
j][0] * orb_vel[
i][0] +
200 ecmat[
j][1] * orb_vel[
i][1] +
201 ecmat[
j][2] * orb_vel[
i][2];
203 velr[
i][0] += posr[
i][1] * omegae;
204 velr[
i][1] -= posr[
i][0] * omegae;
208 for (
size_t i = 0;
i < n_att_rec;
i++) {
209 double ecq[4], qt2[4];
214 memcpy(qt1, &att_quat[
i][1], 3 *
sizeof(
float));
215 qt1[3] = att_quat[
i][0];
217 qprod(ecq, qt1, qt2);
218 for (
size_t j = 0;
j < 4;
j++) quatr[
i][
j] = qt2[
j];
223 q_interp(n_att_rec, sdim, att_time, quatr, stime, quati);
226 for (
size_t i = 0;
i < sdim;
i++) {
227 stime[
i] = stime[
i] + timeoff;
234 orb_interp(n_orb_rec, sdim, orb_time, posr, velr, stime, posi, veli);
238 float *
xlon =
new float[sdim * pdim]();
239 float *
xlat =
new float[sdim * pdim]();
240 short *
solz =
new short[sdim * pdim]();
241 short *
sola =
new short[sdim * pdim]();
242 short *
senz =
new short[sdim * pdim]();
243 short *
sena =
new short[sdim * pdim]();
244 short *
range =
new short[sdim * pdim]();
245 uint8_t *qfl =
new uint8_t[sdim * pdim]();
248 for (
size_t i = 0;
i < sdim * pdim;
i++) {
261 for (
size_t i = 0;
i < pdim;
i++) {
262 double alp = atan(((
double)pdim / 2 -
i + 40) * 0.01 /
focal_length);
264 pview[
i][1] = sin(alp);
265 pview[
i][2] = cos(alp);
270 l_sun(sdim,
iyr, iday, stime, sunr);
273 double sc_to_hwk[3][3];
274 for (
size_t i = 0;
i < 3;
i++)
275 for (
size_t j = 0;
j < 3;
j++) sc_to_hwk[
i][
j] = 0.0;
278 sc_to_hwk[0][2] = 1.0;
280 sc_to_hwk[1][1] = 1.0;
281 sc_to_hwk[2][0] = -1.0;
283 float pitchoff = -0.8;
284 float rpyoff[3] = {rolloff,pitchoff,0.0};
287 gsl_matrix *smat = gsl_matrix_alloc(3, 3);
289 for (
size_t i = 0;
i < sdim;
i++) {
290 if (stime[
i] > -900.0) {
295 qtom(quati[
i], qmat);
297 gsl_matrix_view A = gsl_matrix_view_array(&sc_to_hwk[0][0], 3, 3);
298 gsl_matrix_view B = gsl_matrix_view_array(&qmat[0][0], 3, 3);
300 gsl_blas_dgemm(CblasNoTrans, CblasNoTrans, 1.0,
301 &A.matrix, &B.matrix, 0.0, smat);
304 double *ptr_C = gsl_matrix_ptr(smat, 0, 0);
305 mat2rpy(posi[
i], veli[
i], (
double(*)[3])ptr_C, rpy[
i], om);
307 for (
size_t j = 0;
j < 3;
j++) ang[
i][
j] = rpy[
i][
j] + rpyoff[
j];
313 gsl_matrix_view
C = gsl_matrix_view_array(&rpym[0][0], 3, 3);
314 gsl_matrix_view D = gsl_matrix_view_array(&om[0][0], 3, 3);
316 gsl_blas_dgemm(CblasNoTrans, CblasNoTrans, 1.0,
317 &
C.matrix, &D.matrix, 0.0, smat);
320 ptr_C = gsl_matrix_ptr(smat, 0, 0);
321 scan_ell(posi[
i], (
double(*)[3])ptr_C, coef);
324 size_t ip =
i * pdim;
326 sunr[
i], pview, pdim, &
xlat[ip], &
xlon[ip],
333 gsl_matrix_free(smat);
338 "$OCDATAROOT/hawkeye/Hawkeye_GEO_Data_Structure.cdl",
339 sdim, &geo_ncid, geo_gid);
343 nc_put_att_text(geo_ncid, NC_GLOBAL,
"date_created", strlen(buf), buf);
347 varname.assign(
"scan_time");
348 status = nc_inq_varid(geo_gid[scan_attr_geo], varname.c_str(), &varid);
349 status = nc_put_var_double(geo_gid[scan_attr_geo], varid, stime);
352 status = nc_put_att_text(geo_ncid, NC_GLOBAL,
353 "time_coverage_start", strlen(tstart), tstart);
355 status = nc_put_att_text(geo_ncid, NC_GLOBAL,
356 "time_coverage_end", strlen(tend), tend);
358 varname.assign(
"att_quat");
359 status = nc_inq_varid(geo_gid[nav_geo], varname.c_str(), &varid);
360 status = nc_put_var_float(geo_gid[nav_geo], varid, (
float *)quati);
363 varname.assign(
"att_ang");
364 status = nc_inq_varid(geo_gid[nav_geo], varname.c_str(), &varid);
365 status = nc_put_var_float(geo_gid[nav_geo], varid, (
float *)ang);
368 varname.assign(
"orb_pos");
369 status = nc_inq_varid(geo_gid[nav_geo], varname.c_str(), &varid);
370 status = nc_put_var_float(geo_gid[nav_geo], varid, (
float *)posi);
373 varname.assign(
"orb_vel");
374 status = nc_inq_varid(geo_gid[nav_geo], varname.c_str(), &varid);
375 status = nc_put_var_float(geo_gid[nav_geo], varid, (
float *)veli);
378 varname.assign(
"sun_ref");
379 status = nc_inq_varid(geo_gid[nav_geo], varname.c_str(), &varid);
380 status = nc_put_var_float(geo_gid[nav_geo], varid, (
float *)sunr);
383 varname.assign(
"sc_to_hawkeye");
384 status = nc_inq_varid(geo_gid[nav_geo], varname.c_str(), &varid);
385 status = nc_put_var_double(geo_gid[nav_geo], varid, (
double *)sc_to_hwk);
388 varname.assign(
"latitude");
389 status = nc_inq_varid(geo_gid[geolocation], varname.c_str(), &varid);
390 status = nc_put_var_float(geo_gid[geolocation], varid,
xlat);
393 varname.assign(
"longitude");
394 status = nc_inq_varid(geo_gid[geolocation], varname.c_str(), &varid);
395 status = nc_put_var_float(geo_gid[geolocation], varid,
xlon);
398 varname.assign(
"range");
399 status = nc_inq_varid(geo_gid[geolocation], varname.c_str(), &varid);
400 status = nc_put_var_short(geo_gid[geolocation], varid,
range);
403 varname.assign(
"quality_flag");
404 status = nc_inq_varid(geo_gid[geolocation], varname.c_str(), &varid);
405 status = nc_put_var_ubyte(geo_gid[geolocation], varid, qfl);
408 varname.assign(
"sensor_azimuth");
409 status = nc_inq_varid(geo_gid[geolocation], varname.c_str(), &varid);
410 status = nc_put_var_short(geo_gid[geolocation], varid,
sena);
413 varname.assign(
"sensor_zenith");
414 status = nc_inq_varid(geo_gid[geolocation], varname.c_str(), &varid);
415 status = nc_put_var_short(geo_gid[geolocation], varid,
senz);
418 varname.assign(
"solar_azimuth");
419 status = nc_inq_varid(geo_gid[geolocation], varname.c_str(), &varid);
420 status = nc_put_var_short(geo_gid[geolocation], varid,
sola);
423 varname.assign(
"solar_zenith");
424 status = nc_inq_varid(geo_gid[geolocation], varname.c_str(), &varid);
425 status = nc_put_var_short(geo_gid[geolocation], varid,
solz);
472 double xnut[3][3], ut1utc;
477 double day =
idy + (sec + ut1utc) / 86400;
478 double gha, gham[3][3];
481 gham[0][0] = cos(gha /
RADEG);
482 gham[1][1] = cos(gha /
RADEG);
484 gham[0][1] = sin(gha /
RADEG);
485 gham[1][0] = -sin(gha /
RADEG);
493 gsl_matrix_view A = gsl_matrix_view_array(&gham[0][0], 3, 3);
494 gsl_matrix_view B = gsl_matrix_view_array(&xnut[0][0], 3, 3);
495 gsl_matrix *
C = gsl_matrix_alloc(3, 3);
497 gsl_blas_dgemm(CblasNoTrans, CblasTrans, 1.0, &A.matrix, &B.matrix, 0.0,
C);
499 gsl_matrix_view D = gsl_matrix_view_array(&j2mod[0][0], 3, 3);
500 gsl_matrix *E = gsl_matrix_alloc(3, 3);
501 gsl_blas_dgemm(CblasNoTrans, CblasNoTrans, 1.0,
C, &D.matrix, 0.0, E);
502 double *ptr_E = gsl_matrix_ptr(E, 0, 0);
504 memcpy(ecmat, ptr_E, 9 *
sizeof(
double));
527 double t =
jday(iyear, 1, iday) - (
double)2451545.5 + sec / 86400;
530 double zeta0 =
t * (2306.2181 + 0.302 *
t + 0.018 *
t *
t) /
RADEG / 3600;
531 double thetap =
t * (2004.3109 - 0.4266 *
t - 0.04160 *
t *
t) /
RADEG / 3600;
532 double xip =
t * (2306.2181 + 1.095 *
t + 0.018 *
t *
t) /
RADEG / 3600;
534 j2mod[0][0] = -sin(zeta0) * sin(xip) + cos(zeta0) * cos(xip) * cos(thetap);
535 j2mod[0][1] = -cos(zeta0) * sin(xip) - sin(zeta0) * cos(xip) * cos(thetap);
536 j2mod[0][2] = -cos(xip) * sin(thetap);
537 j2mod[1][0] = sin(zeta0) * cos(xip) + cos(zeta0) * sin(xip) * cos(thetap);
538 j2mod[1][1] = cos(zeta0) * cos(xip) - sin(zeta0) * sin(xip) * cos(thetap);
539 j2mod[1][2] = -sin(xip) * sin(thetap);
540 j2mod[2][0] = cos(zeta0) * sin(thetap);
541 j2mod[2][1] = -sin(zeta0) * sin(thetap);
542 j2mod[2][2] = cos(thetap);
551 double t =
jday(iyear, 1, iday) - (
double)2451545.5;
553 double xls, gs, xlm,
omega;
554 double dpsi, eps, epsm;
558 xnut[0][0] = cos(dpsi /
RADEG);
559 xnut[1][0] = -sin(dpsi /
RADEG) * cos(epsm /
RADEG);
560 xnut[2][0] = -sin(dpsi /
RADEG) * sin(epsm /
RADEG);
561 xnut[0][1] = sin(dpsi /
RADEG) * cos(eps /
RADEG);
562 xnut[1][1] = cos(dpsi /
RADEG) * cos(eps /
RADEG) * cos(epsm /
RADEG) +
564 xnut[2][1] = cos(dpsi /
RADEG) * cos(eps /
RADEG) * sin(epsm /
RADEG) -
566 xnut[0][2] = sin(dpsi /
RADEG) * sin(eps /
RADEG);
567 xnut[1][2] = cos(dpsi /
RADEG) * sin(eps /
RADEG) * cos(epsm /
RADEG) -
569 xnut[2][2] = cos(dpsi /
RADEG) * sin(eps /
RADEG) * sin(epsm /
RADEG) +
586 xls = (
double)280.46592 + ((
double)0.9856473516) *
t;
587 xls = fmod(xls, (
double)360);
590 gs = (
double)357.52772 + ((
double)0.9856002831) *
t;
591 gs = fmod(gs, (
double)360);
594 xlm = (
double)218.31643 + ((
double)13.17639648) *
t;
595 xlm = fmod(xlm, (
double)360);
605 double &dpsi,
double &eps,
double &epsm) {
618 1.3187 * sin(2. * xls /
RADEG) + 0.1426 * sin(gs /
RADEG) -
619 0.2274 * sin(2. * xlm /
RADEG);
622 epsm = (
double)23.439291 - ((
double)3.560e-7) *
t;
625 double deps = 9.2025 * cos(
omega /
RADEG) + 0.5736 * cos(2. * xls /
RADEG);
628 eps = epsm + deps / 3600;
639 static int32_t ijd[25000];
640 static double ut1[25000];
641 string utcpole =
"$OCVARROOT/modis/utcpole.dat";
642 static bool first =
true;
649 ifstream utcpfile(
utcpole.c_str());
650 if (utcpfile.is_open()) {
651 getline(utcpfile,
line);
652 getline(utcpfile,
line);
653 while (getline(utcpfile,
line)) {
656 istr.str(
line.substr(0, 5));
659 istr.str(
line.substr(44, 9));
667 cout <<
utcpole.c_str() <<
" not found" << endl;
673 int mjd =
jday(iyear, 1, iday) - 2400000;
696 double fday =
day - iday;
698 double t =
jd - (
double)2451545.5 + fday;
701 double gmst = (
double)100.4606184 + (
double)0.9856473663 *
t +
705 double xls, gs, xlm,
omega;
706 double dpsi, eps, epsm;
711 gha = gmst + dpsi * cos(eps /
RADEG) + fday * 360;
712 gha = fmod(gha, (
double)360);
728 for(
size_t i=0;
i<3;
i++) {
729 for (
size_t j=0;
j<3;
j++) {
738 double c1=cos(
a[0]/
RADEG);
739 double s1=sin(
a[0]/
RADEG);
740 double c2=cos(
a[1]/
RADEG);
741 double s2=sin(
a[1]/
RADEG);
742 double c3=cos(
a[2]/
RADEG);
743 double s3=sin(
a[2]/
RADEG);
764 gsl_matrix_view A = gsl_matrix_view_array(&xm2[0][0], 3, 3);
765 gsl_matrix_view B = gsl_matrix_view_array(&xm1[0][0], 3, 3);
766 gsl_matrix *E = gsl_matrix_alloc(3, 3);
767 gsl_blas_dgemm(CblasNoTrans, CblasNoTrans, 1.0,
768 &A.matrix, &B.matrix, 0.0, E);
769 double *ptr_E = gsl_matrix_ptr(E, 0, 0);
770 memcpy(xmm, ptr_E, 9 *
sizeof(
double));
773 gsl_matrix_view
C = gsl_matrix_view_array(&xm3[0][0], 3, 3);
774 gsl_matrix_view D = gsl_matrix_view_array(&xmm[0][0], 3, 3);
775 gsl_matrix *
F = gsl_matrix_alloc(3, 3);
776 gsl_blas_dgemm(CblasNoTrans, CblasNoTrans, 1.0,
777 &
C.matrix, &D.matrix, 0.0,
F);
778 double *ptr_F = gsl_matrix_ptr(
F, 0, 0);
779 memcpy(xm, ptr_F, 9 *
sizeof(
double));
786 int mtoq(
double rm[3][3],
double q[4]) {
793 double cphi = (rm[0][0] + rm[1][1] + rm[2][2] - 1) / 2;
797 double ssphi = (pow(rm[0][1] - rm[1][0], 2) +
798 pow(rm[2][0] - rm[0][2], 2) +
799 pow(rm[1][2] - rm[2][1], 2)) /
801 phi = asin(sqrt(ssphi));
802 if (
cphi < 0) phi =
PI - phi;
806 e[0] = (rm[2][1] - rm[1][2]) / (sin(phi) * 2);
807 e[1] = (rm[0][2] - rm[2][0]) / (sin(phi) * 2);
808 e[2] = (rm[1][0] - rm[0][1]) / (sin(phi) * 2);
809 double norm = sqrt(e[0] * e[0] + e[1] * e[1] + e[2] * e[2]);
815 q[0] = e[0] * sin(phi / 2);
816 q[1] = e[1] * sin(phi / 2);
817 q[2] = e[2] * sin(phi / 2);
823 int qprod(
double q1[4],
float q2[4],
double q3[4]) {
826 q3[0] = q1[0] * q2[3] + q1[1] * q2[2] - q1[2] * q2[1] + q1[3] * q2[0];
827 q3[1] = -q1[0] * q2[2] + q1[1] * q2[3] + q1[2] * q2[0] + q1[3] * q2[1];
828 q3[2] = q1[0] * q2[1] - q1[1] * q2[0] + q1[2] * q2[3] + q1[3] * q2[2];
829 q3[3] = -q1[0] * q2[0] - q1[1] * q2[1] - q1[2] * q2[2] + q1[3] * q2[3];
834 int qprod(
float q1[4],
float q2[4],
float q3[4]) {
837 q3[0] = q1[0] * q2[3] + q1[1] * q2[2] - q1[2] * q2[1] + q1[3] * q2[0];
838 q3[1] = -q1[0] * q2[2] + q1[1] * q2[3] + q1[2] * q2[0] + q1[3] * q2[1];
839 q3[2] = q1[0] * q2[1] - q1[1] * q2[0] + q1[2] * q2[3] + q1[3] * q2[2];
840 q3[3] = -q1[0] * q2[0] - q1[1] * q2[1] - q1[2] * q2[2] + q1[3] * q2[3];
876 double a0[3], a1[3], a2[3], a3[3];
891 for (
size_t i = 0;
i < sdim;
i++) {
893 for (
size_t j = ind;
j < n_orb_rec;
j++) {
901 double dt = torb[ind + 1] - torb[ind];
902 for (
size_t j = 0;
j < 3;
j++) {
904 a1[
j] =
v[ind][
j] * dt;
905 a2[
j] = 3 *
p[ind + 1][
j] - 3 *
p[ind][
j] - 2 *
v[ind][
j] * dt -
907 a3[
j] = 2 *
p[ind][
j] - 2 *
p[ind + 1][
j] +
v[ind][
j] * dt +
912 double x = (
time[
i] - torb[ind]) / dt;
915 for (
size_t j = 0;
j < 3;
j++) {
916 posi[
i][
j] = a0[
j] + a1[
j] *
x + a2[
j] * x2 + a3[
j] * x3;
917 veli[
i][
j] = (a1[
j] + 2 * a2[
j] *
x + 3 * a3[
j] * x2) / dt;
931 for (
size_t i = 0;
i < sdim;
i++) {
933 for (
size_t j = ind;
j < n_att_rec;
j++) {
941 double dt = tq[ind + 1] - tq[ind];
949 qprod(qin,
q[ind + 1], qr);
950 memcpy(e, qr, 3 *
sizeof(
double));
951 double sto2 = sqrt(e[0] * e[0] + e[1] * e[1] + e[2] * e[2]);
952 for (
size_t j = 0;
j < 3;
j++) e[
j] /= sto2;
955 double x = (
time[
i] - tq[ind]) / dt;
957 for (
size_t j = 0;
j < 3;
j++) qri[
j] = e[
j] * sto2 *
x;
960 memcpy(qi[
i], qp, 4 *
sizeof(
float));
966 int l_sun(
size_t sdim, int32_t
iyr, int32_t iday,
double *sec,
975 for (
size_t i = 0;
i < sdim;
i++) {
976 double day = iday + sec[
i] / 86400;
979 double ghar = gha /
RADEG;
982 float temp0 = sunr[
i][0] * cos(ghar) + sunr[
i][1] * sin(ghar);
983 float temp1 = sunr[
i][1] * cos(ghar) - sunr[
i][0] * sin(ghar);
1000 float xk = 0.0056932;
1004 int16_t iyear =
iyr;
1007 for (
size_t i = 0;
i < sdim;
i++) {
1009 jday(iyear, 1, iday) - (
double)2451545.0 + (sec[
i] - 43200) / 86400;
1011 double xls, gs, xlm,
omega;
1012 double dpsi, eps, epsm;
1021 double g2 = 50.40828 + 1.60213022 *
t;
1022 g2 = fmod(g2, (
double)360);
1025 double g4 = 19.38816 + 0.52402078 *
t;
1026 g4 = fmod(g4, (
double)360);
1029 double g5 = 20.35116 + 0.08309121 *
t;
1030 g5 = fmod(g5, (
double)360);
1034 1.00014 - 0.01671 * cos(gs /
RADEG) - 0.00014 * cos(2. * gs /
RADEG);
1037 double dls = (6893. - 4.6543463e-4 *
t) * sin(gs /
RADEG) +
1038 72. * sin(2. * gs /
RADEG) - 7. * cos((gs - g5) /
RADEG) +
1039 6. * sin((xlm - xls) /
RADEG) +
1040 5. * sin((4. * gs - 8. * g4 + 3. * g5) /
RADEG) -
1041 5. * cos((2. * gs - 2. * g2) /
RADEG) -
1042 4. * sin((gs - g2) /
RADEG) +
1043 4. * cos((4. * gs - 8. * g4 + 3. * g5) /
RADEG) +
1044 3. * sin((2. * gs - 2. * g2) /
RADEG) - 3. * sin(g5 /
RADEG) -
1045 3. * sin((2. * gs - 2. * g5) /
RADEG);
1047 double xlsg = xls + dls / 3600;
1051 double xlsa = xlsg + dpsi - xk / rs;
1054 sun[
i][0] = cos(xlsa /
RADEG);
1065 rm[0][0] =
q[0] *
q[0] -
q[1] *
q[1] -
q[2] *
q[2] +
q[3] *
q[3];
1066 rm[0][1] = 2 * (
q[0] *
q[1] +
q[2] *
q[3]);
1067 rm[0][2] = 2 * (
q[0] *
q[2] -
q[1] *
q[3]);
1068 rm[1][0] = 2 * (
q[0] *
q[1] -
q[2] *
q[3]);
1069 rm[1][1] = -
q[0] *
q[0] +
q[1] *
q[1] -
q[2] *
q[2] +
q[3] *
q[3];
1070 rm[1][2] = 2 * (
q[1] *
q[2] +
q[0] *
q[3]);
1071 rm[2][0] = 2 * (
q[0] *
q[2] +
q[1] *
q[3]);
1072 rm[2][1] = 2 * (
q[1] *
q[2] -
q[0] *
q[3]);
1073 rm[2][2] = -
q[0] *
q[0] -
q[1] *
q[1] +
q[2] *
q[2] +
q[3] *
q[3];
1078 int scan_ell(
float p[3],
double sm[3][3],
double coef[10]) {
1093 double re = 6378.137;
1094 double f = 1 / 298.257;
1095 double omf2 = (1 -
f) * (1 -
f);
1101 coef[0] = 1 + (
rd - 1) * sm[0][2] * sm[0][2];
1102 coef[1] = 1 + (
rd - 1) * sm[1][2] * sm[1][2];
1103 coef[2] = 1 + (
rd - 1) * sm[2][2] * sm[2][2];
1104 coef[3] = (
rd - 1) * sm[0][2] * sm[1][2] * 2;
1105 coef[4] = (
rd - 1) * sm[0][2] * sm[2][2] * 2;
1106 coef[5] = (
rd - 1) * sm[1][2] * sm[2][2] * 2;
1107 coef[6] = (sm[0][0] *
p[0] + sm[0][1] *
p[1] + sm[0][2] *
p[2] *
rd) * 2;
1108 coef[7] = (sm[1][0] *
p[0] + sm[1][1] *
p[1] + sm[1][2] *
p[2] *
rd) * 2;
1109 coef[8] = (sm[2][0] *
p[0] + sm[2][1] *
p[1] + sm[2][2] *
p[2] *
rd) * 2;
1110 coef[9] =
p[0] *
p[0] +
p[1] *
p[1] +
p[2] *
p[2] *
rd -
re *
re;
1175 float f = 1 / 298.257;
1176 float omf2 = (1 -
f) * (1 -
f);
1177 gsl_vector *
C = gsl_vector_alloc(3);
1179 for (
size_t i = 0;
i <
npix;
i++) {
1182 float o = coef[0] * pview[
i][0] * pview[
i][0] +
1183 coef[1] * pview[
i][1] * pview[
i][1] +
1184 coef[2] * pview[
i][2] * pview[
i][2] +
1185 coef[3] * pview[
i][0] * pview[
i][1] +
1186 coef[4] * pview[
i][0] * pview[
i][2] +
1187 coef[5] * pview[
i][1] * pview[
i][2];
1190 coef[6] * pview[
i][0] + coef[7] * pview[
i][1] + coef[8] * pview[
i][2];
1194 float r =
p *
p - 4 *
q * o;
1208 float d = (-
p - sqrt(
r)) / (2 * o);
1210 for (
size_t j = 0;
j < 3;
j++) x1[
j] = d * pview[
i][
j];
1214 gsl_matrix_view A = gsl_matrix_view_array((
double *)smat, 3, 3);
1215 gsl_vector_view B = gsl_vector_view_array(x1, 3);
1217 gsl_blas_dgemv(CblasTrans, 1.0, &A.matrix, &B.vector, 0.0,
C);
1219 float rh[3], geovec[3];
1220 double *ptr_C = gsl_vector_ptr(
C, 0);
1221 for (
size_t j = 0;
j < 3;
j++) {
1223 geovec[
j] =
pos[
j] + rh[
j];
1227 float uxy = geovec[0] * geovec[0] + geovec[1] * geovec[1];
1228 float temp = sqrt(geovec[2] * geovec[2] +
omf2 *
omf2 * uxy);
1231 up[0] =
omf2 * geovec[0] / temp;
1232 up[1] =
omf2 * geovec[1] / temp;
1233 up[2] = geovec[2] / temp;
1234 float upxy = sqrt(up[0] * up[0] + up[1] * up[1]);
1237 ea[0] = -up[1] / upxy;
1238 ea[1] = up[0] / upxy;
1243 no[0] = -up[2] * ea[1];
1244 no[1] = up[2] * ea[0];
1245 no[2] = up[0] * ea[1] - up[1] * ea[0];
1250 range[
i] = (short)((d - 400) * 10);
1254 rl[0] = -ea[0] * rh[0] - ea[1] * rh[1] - ea[2] * rh[2];
1255 rl[1] = -no[0] * rh[0] - no[1] * rh[1] - no[2] * rh[2];
1256 rl[2] = -up[0] * rh[0] - up[1] * rh[1] - up[2] * rh[2];
1258 sl[0] = sunr[0] * ea[0] + sunr[1] * ea[1] + sunr[2] * ea[2];
1259 sl[1] = sunr[0] * no[0] + sunr[1] * no[1] + sunr[2] * no[2];
1260 sl[2] = sunr[0] * up[0] + sunr[1] * up[1] + sunr[2] * up[2];
1264 atan2(sqrt(sl[0] * sl[0] + sl[1] * sl[1]), sl[2]));
1267 if (
solz[
i] > 0.01)
sola[
i] = (short)(100 *
RADEG * atan2(sl[0], sl[1]));
1271 atan2(sqrt(rl[0] * rl[0] + rl[1] * rl[1]), rl[2]));
1274 if (
senz[
i] > 0.01)
sena[
i] = (short)(100 *
RADEG * atan2(rl[0], rl[1]));
1284 int mat2rpy(
float pos[3],
float vel[3],
double smat[3][3],
float rpy[3],
double om[3][3]) {
1302 double f = 1 / (
double)298.257;
1303 double omegae = 7.29211585494e-5;
1304 double omf2 = (1 -
f) * (1 -
f);
1308 for (
size_t j = 0;
j < 3;
j++) {
1312 v[0] -=
p[1] * omegae;
1313 v[1] +=
p[0] * omegae;
1316 double pm = sqrt(
p[0] *
p[0] +
p[1] *
p[1] +
p[2] *
p[2]);
1317 double omf2p = (
omf2 * rem +
pm - rem) /
pm;
1318 double pxy =
p[0] *
p[0] +
p[1] *
p[1];
1319 double temp = sqrt(
p[2] *
p[2] + omf2p * omf2p * pxy);
1322 z[0] = -omf2p *
p[0] / temp;
1323 z[1] = -omf2p *
p[1] / temp;
1324 z[2] = -
p[2] / temp;
1328 on[0] =
v[1] * z[2] -
v[2] * z[1];
1329 on[1] =
v[2] * z[0] -
v[0] * z[2];
1330 on[2] =
v[0] * z[1] -
v[1] * z[0];
1332 double onm = sqrt(
on[0] *
on[0] +
on[1] *
on[1] +
on[2] *
on[2]);
1335 for (
size_t j = 0;
j < 3;
j++)
y[
j] = -
on[
j] / onm;
1339 x[0] =
y[1] * z[2] -
y[2] * z[1];
1340 x[1] =
y[2] * z[0] -
y[0] * z[2];
1341 x[2] =
y[0] * z[1] -
y[1] * z[0];
1345 memcpy(&om[0][0], &
x, 3 *
sizeof(
double));
1346 memcpy(&om[1][0], &
y, 3 *
sizeof(
double));
1347 memcpy(&om[2][0], &z, 3 *
sizeof(
double));
1351 gsl_matrix_view rm_mat = gsl_matrix_view_array(&rm[0][0], 3, 3);
1355 gsl_permutation *perm = gsl_permutation_alloc(3);
1360 memcpy(&B_mat[0][0], &om[0][0], 9 *
sizeof(
double));
1361 gsl_matrix_view B = gsl_matrix_view_array(&B_mat[0][0], 3, 3);
1363 gsl_linalg_LU_decomp(&B.matrix, perm, &
s);
1367 gsl_matrix_view inv_mat = gsl_matrix_view_array(&inv[0][0], 3, 3);
1369 gsl_linalg_LU_invert(&B.matrix, perm, &inv_mat.matrix);
1371 gsl_matrix_view A = gsl_matrix_view_array(&smat[0][0], 3, 3);
1373 gsl_blas_dgemm(CblasNoTrans, CblasNoTrans, 1.0, &A.matrix, &inv_mat.matrix,
1374 0.0, &rm_mat.matrix);
1376 gsl_permutation_free(perm);
1379 rpy[0] =
RADEG * atan(-rm[2][1] / rm[2][2]);
1383 rpy[1] =
RADEG * asin(rm[2][0]);
1384 rpy[2] =
RADEG * atan(-rm[1][0] / rm[0][0]);