OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
GEO_ellip_position.c
Go to the documentation of this file.
1 #include "PGS_CSC.h"
2 #include "PGS_MODIS_35251.h"
3 #include "GEO_earth.h"
4 #include "GEO_global_arrays.h"
5 #include "GEO_util.h"
6 #include "smfio.h"
7 
9  int const scan_number,
10  int const sample_number,
11  int const num_detectors,
12  double u_inst[][3],
13  double ecr_sc_sample_position[][3],
14  double ecr_sc_velocity[][3],
15  double T_inst2ecr[][3][3],
16  double ecr_sample_position[][MAX_PADDED][3],
17  double ellip_sample_position[][MAX_PADDED][3],
18  unsigned char sample_flags[][MAX_PADDED],
19  double sample_view_vec[][MAX_PADDED][3]
20  )
21 /*
22 !C*****************************************************************************
23 !Description:
24  Routine in Earth Location group of the Level-1A geolocation software to
25  calculate the ellipsoidal position of a pixel. It transforms each view
26  vector to the ECR frame and solves for the magnitude of the vector
27  (See Geolocation ATBD section 3.1.3.2). Finally, it computes the
28  geodetic latitude and longitude for the pixel and stores them in the
29  global array. If the view vector for a detector does not intersect the
30  earth ellipsoid, no ecr_sample_position nor ellip_sample_position will
31  be determined, and the sample_view_vec will not be rescaled for that
32  detector.
33 
34  GEO_ellip_position initializes the terrain sample position validity
35  sample_flags, setting NO_ELLIPSE_INTERSECT for detectors with view
36  vectors that do not intersect the earth ellipsoid. The
37  INVALID_INPUT_DATA flag is not set if a routine failure occurs, it
38  being set for each detector in the frame in GEO_locate_one_scan.
39 
40 !Input Parameters:
41  scan_number The scan number
42  sample_number The sample number within the scan
43  num_detectors Number of detectors for the sample
44  u_inst View vectors for each detector in the
45  instrument coordinate system (meters).
46  ecr_sc_sample_position The spacecraft position.
47  ecr_sc_velocity The spacecraft velocity.
48  T_inst2ecr Matrix for conversion from instrument to ECR
49  coordinates.
50 
51 !Output Parameters:
52  ecr_sample_position Ground positions in ECR coordinates.
53  ellip_sample_position Ground positions without terrain correction.
54  sample_flags Error flags for each sample.
55  sample_view_vec View vector from satellite to ground position.
56 
57 Return Values:
58  FAIL If arguments are invalid or PGS_CSC_GetEarthFigure()
59  fails.
60  SUCCESS Otherwise
61 
62 Externally Defined:
63  DETECTORS_QKM "GEO_geo.h"
64  FAIL "GEO_basic.h"
65  INVALID_INPUT_DATA "GEO_geo.h"
66  MAX_SCAN_NUMBER "GEO_geo.h"
67  MODIS_E_BAD_INPUT_ARG "PGS_MODIS_35251.h"
68  MODIS_E_BAD_VIEW_VEC "PGS_MODIS_35251.h"
69  MODIS_E_GEO "PGS_MODIS_35251.h"
70  MODIS_W_SCAN_OFF "PGS_MODIS_35251.h"
71  NO_ELLIPSE_INTERSECT "GEO_geo.h"
72  MAX_PADDED "GEO_geo.h"
73  PGSd_GEO_ERROR_VALUE "PGS_TD.h"
74  PGS_S_SUCCESS "PGS_SMF.h"
75  SUCCESS "GEO_basic.h"
76 
77 Called by: GEO_earth_location
78 
79 Routines called:
80  PGS_CSC_ECRtoGEO "PGS_CSC.h"
81  PGS_CSC_GetEarthFigure "PGS_CSC.h"
82  modsmf "smfio.h"
83 
84 !Revision History:
85  $Log: GEO_ellip_position.c,v $
86  Revision 6.4 2010/06/29 18:45:31 kuyper
87  Replaced floating point equality test with an inequality.
88 
89  Revision 6.3 2009/05/31 19:02:17 kuyper
90  Corrected to initialize p_prime_sq, up_prod, u_prime_sq where needed.
91  Improved error messages.
92 
93  Revision 6.2 2009/05/15 17:00:18 xgeng
94  Minor correction on error messages.
95 
96  Xu Geng (xu.geng@saic.com)
97  Revision 6.1 2009/05/06 19:34:43 xgeng
98  Code updated to match the PDL change made in revision 6.1, 6.2 and 6.3.
99 
100  Revision 4.4 2003/09/03 17:17:04 vlin
101  corrected a typo.
102 
103  Revision 4.3 2003/08/28 15:56:51 kuyper
104  Corrected prolog.
105 
106  Revision 4.2 2003/08/22 14:24:21 kuyper
107  Removed T_inst2ecr and sc_attitude globals.
108 
109  Revision 4.1 2003/08/08 19:36:28 vlin
110  Calls to GEO_interp_ephemeris_attitude() and GEO_get_T_inst2ecr() are moved
111  up to a higher level. As a result, ecr_sc_position, ecr_sc_velocity,
112  scan_start_time, and T_inst2ecr are now inputs rather than outputs.
113  Removed intitialization of sc_attitude.
114  Shifted messages to MODIS_E_GEO, where applicable.
115 
116  Revision 2.4 1999/01/29 20:14:01 kuyper
117  Removed max_extrap from GEO_interp_ephemeris() argument list.
118 
119  4/25/95
120  Ruiming Chen
121  Finished coding.
122 
123 !Team-unique Header:
124  This software is developed by the MODIS Science Data Support
125  Team for the National Aeronautics and Space Administration,
126  Goddard Space Flight Center, under contract NAS5-32373.
127 
128 Requirements:
129  PR03-F-3.2.2-1
130  PR03-F-3.2.3-1
131  PR03-F-3.2.3-2
132  PR03-F-3.2.4-1
133  PR03-I-1
134  PR03-I-2
135 
136 !END*************************************************************************
137 */
138 
139 {
140  static PGSt_double equat=-1.0; /* equatorial radius of the earth */
141  static PGSt_double polar=-1.0; /* polar radius of the earth. */
142  PGSt_double p_prime[3]; /* rescaled sc position */
143  double p_prime_sq = 0.0; /* square of p_prime_length */
144  PGSt_SMF_status PGS_error_code; /* SDP toolkit function return value */
145  int det; /* detector index */
146  int ecr; /* iteration parameter */
147  char msgbuf[128] = "";
148  static char filefunc[] = __FILE__ ", GEO_ellip_position";
149 
150 /****************************************************************************
151 calculate from here
152 ****************************************************************************/
153 
154  if( scan_number < 0 || scan_number >= MAX_SCAN_NUMBER ||
155  num_detectors < 0 || num_detectors > DETECTORS_QKM ||
156  sample_number < 0 || sample_number >= MAX_PADDED ||
157  u_inst == NULL || ecr_sc_sample_position == NULL ||
158  ecr_sc_velocity == NULL || T_inst2ecr == NULL ||
159  ecr_sample_position == NULL || ellip_sample_position == NULL ||
160  sample_flags == NULL || sample_view_vec == NULL )
161  {
162  sprintf(msgbuf, "scan:%d detectors:%d sample:%d u_inst:%p "
163  "ecr_sc_sample_position:%p ecr_sc_velocity:%p "
164  "T_inst2ecr:%p ecr_sample_position:%p "
165  "ellip_sample_position:%p sample_flags:%p "
166  "sample_view_vec:%p",
167  scan_number, num_detectors, sample_number, (void *)u_inst,
168  (void *)ecr_sc_sample_position, (void *)ecr_sc_velocity,
169  (void *)T_inst2ecr, (void *)ecr_sample_position,
170  (void *)ellip_sample_position, (void *)sample_flags,
171  (void *)sample_view_vec
172  );
173 
174  modsmf(MODIS_E_BAD_INPUT_ARG, msgbuf, filefunc);
175  return FAIL;
176  }
177 
178  if (ecr_sc_sample_position[sample_number][0] >= PGSd_GEO_ERROR_VALUE) {
179  for (det = 0; det < num_detectors; det++)
180  sample_flags[det][sample_number] = INVALID_INPUT_DATA;
181  return SUCCESS;
182  }
183 
184  for (det=0; det<num_detectors ; det++)
185  sample_flags[det][sample_number] = 0;
186 
187  if (equat < 0.0) {
188  /* the equatorial and polar earth radii have not been set */
189  PGS_error_code = PGS_CSC_GetEarthFigure(EARTH_MODEL, &equat, &polar);
190  if (PGS_error_code!=PGS_S_SUCCESS)
191  {
192  modsmf(MODIS_E_GEO, "PGS_CSC_GetEarthFigure(\"" EARTH_MODEL "\")",
193  filefunc);
194  return FAIL;
195  }
196  }
197 
198  /* Rescale orbit position vector */
199  p_prime[0] = ecr_sc_sample_position[sample_number][0] / equat;
200  p_prime[1] = ecr_sc_sample_position[sample_number][1] / equat;
201  p_prime[2] = ecr_sc_sample_position[sample_number][2] / polar;
202 
203  for (ecr = 0; ecr < 3; ecr ++)
204  p_prime_sq += p_prime[ecr]*p_prime[ecr];
205 
206  /* Loop through detectors in sample */
207  for (det = 0; det < num_detectors; det++)
208  {
209  PGSt_double u_prime[3]; /* rescaled view vec */
210  double up_prod_sq; /* square of up_prod */
211  double sqrt_arg; /* argument of square root in the calculation of d */
212  double d; /* scaling factor of the viewing vector */
213  double up_prod = 0.0; /* product between u_prime and p_prime */
214  double u_prime_sq = 0.0; /* square of u_prime_length */
215 
216  /* Transform the viewing vector to ECR */
217  for (ecr = 0; ecr < 3; ecr ++) {
218  int inst; /* iteration parameter */
219  sample_view_vec[det][sample_number][ecr] = 0.0;
220 
221  for (inst = 0; inst < 3; inst ++) {
222  sample_view_vec[det][sample_number][ecr] +=
223  T_inst2ecr[sample_number][ecr][inst]*u_inst[det][inst];
224  }
225  }
226 
227  /* Rescale viewing vector */
228  u_prime[0] = sample_view_vec[det][sample_number][0] / equat;
229  u_prime[1] = sample_view_vec[det][sample_number][1] / equat;
230  u_prime[2] = sample_view_vec[det][sample_number][2] / polar;
231 
232  /* Compute dot product of u_prime and p_prime
233  and squared magnitudes of u_prime and p_prime */
234  for (ecr = 0; ecr < 3; ecr ++) {
235  up_prod += u_prime[ecr]*p_prime[ecr];
236  u_prime_sq += u_prime[ecr]*u_prime[ecr];
237  }
238 
239  up_prod_sq = up_prod * up_prod;
240 
241  /* Check for negative under square root (scan off of Earth) */
242  sqrt_arg = up_prod_sq - u_prime_sq*(p_prime_sq - 1.0);
243  if (sqrt_arg < 0.0 || up_prod>=0.0) { /* No real ellipsoid intersection*/
244  /* call SDP function to report event */
245  modsmf(MODIS_W_SCAN_OFF, "", filefunc);
246  sample_flags[det][sample_number] |= NO_ELLIPSE_INTERSECT;
247  }
248  else if ( (-up_prod - sqrt(sqrt_arg))/DBL_MAX >= u_prime_sq)
249  { /* Calculation of d will produce overflow. */
250  modsmf(MODIS_E_BAD_VIEW_VEC, "", filefunc);
251  sample_flags[det][sample_number] |= INVALID_INPUT_DATA;
252  }
253  else
254  {
255  PGSt_double latitude; /* latitude of the ellipsoid position */
256  PGSt_double longitude; /* longitude of the ellipsoid position */
257  PGSt_double altitude; /* altitude of the ellipsoid position */
258 
259  d = (-up_prod - sqrt(sqrt_arg)) / u_prime_sq;
260 
261  /* calculate the geocentric position vector */
262  for (ecr = 0; ecr < 3; ++ecr) {
263  sample_view_vec[det][sample_number][ecr] *= d;
264  ecr_sample_position[det][sample_number][ecr] =
265  ecr_sc_sample_position[sample_number][ecr] +
266  sample_view_vec[det][sample_number][ecr];
267  }
268 
269  /* calculate the geodetic lat and lon */
270 
271  if (PGS_CSC_ECRtoGEO( ecr_sample_position[det][sample_number],
272  EARTH_MODEL, &longitude, &latitude, &altitude) != PGS_S_SUCCESS)
273  {
274  modsmf(MODIS_E_GEO, "PGS_CSC_ECRtoGEO(\"" EARTH_MODEL "\")", filefunc);
275  sample_flags[det][sample_number] |= INVALID_INPUT_DATA;
276  continue;
277  }
278 
279  /* store latitude and longitude in global variable */
280  ellip_sample_position[det][sample_number][LAT_IDX] = latitude;
281  ellip_sample_position[det][sample_number][LON_IDX] = longitude;
282  ellip_sample_position[det][sample_number][HT_IDX] = 0.0;
283  }
284  }
285 
286  return SUCCESS;
287 }
288 
int GEO_ellip_position(int const scan_number, int const sample_number, int const num_detectors, double u_inst[][3], double ecr_sc_sample_position[][3], double ecr_sc_velocity[][3], double T_inst2ecr[][3][3], double ecr_sample_position[][MAX_PADDED][3], double ellip_sample_position[][MAX_PADDED][3], unsigned char sample_flags[][MAX_PADDED], double sample_view_vec[][MAX_PADDED][3])
#define MODIS_E_BAD_VIEW_VEC
#define SUCCESS
Definition: ObpgReadGrid.h:15
real(single), dimension(:,:), allocatable longitude
#define FAIL
Definition: ObpgReadGrid.h:18
#define NULL
Definition: decode_rs.h:63
#define MODIS_E_BAD_INPUT_ARG
const unsigned char NO_ELLIPSE_INTERSECT
real(single), dimension(:,:), allocatable latitude
#define MAX_PADDED
Definition: GEO_geo.h:84
@ HT_IDX
#define MODIS_E_GEO
@ LON_IDX
#define EARTH_MODEL
Definition: GEO_earth.h:118
@ LAT_IDX
const int MAX_SCAN_NUMBER
#define MODIS_W_SCAN_OFF
#define DBL_MAX
Definition: make_L3_v1.1.c:60
const unsigned char INVALID_INPUT_DATA
#define DETECTORS_QKM
Definition: GEO_geo.h:87