OSSIM - Open Source Software Image Map  Version 1.9.0 (20180803)
ossimRadarSat2RPCModel.cpp
Go to the documentation of this file.
1 //----------------------------------------------------------------------------
2 //
3 // "Copyright Centre National d'Etudes Spatiales"
4 //
5 // License: LGPL
6 //
7 // See LICENSE.txt file in the top level directory for more details.
8 //
9 //----------------------------------------------------------------------------
10 // $Id$
11 
12 #include <cmath>
13 
14 #include <ossimRadarSat2RPCModel.h>
15 #include <ossimPluginCommon.h>
17 #include <ossim/base/ossimCommon.h>
20 #include <ossim/base/ossimNotify.h>
21 #include <ossim/base/ossimRefPtr.h>
22 #include <ossim/base/ossimString.h>
23 #include <ossim/base/ossimTrace.h>
26 
30 
31 #include <otb/GalileanEphemeris.h>
33 #include <otb/GMSTDateTime.h>
34 
35 #include <otb/SensorParams.h>
36 #include <otb/SarSensor.h>
37 
38 namespace ossimplugins
39 {
40 
41 // Keyword constants:
42 static const char LOAD_FROM_PRODUCT_FILE_KW[] = "load_from_product_file_flag";
43 static const char PRODUCT_XML_FILE_KW[] = "product_xml_filename";
44 
45 // Static trace for debugging
46 static ossimTrace traceDebug("ossimRadarSat2RPCModel:debug");
47 
48 
49 RTTI_DEF1(ossimRadarSat2RPCModel, "ossimRadarSat2RPCModel", ossimRpcModel);
50 
52  :
53  ossimRpcModel(),
54  theDecimation(1.0),
55  theProductXmlFile(ossimFilename::NIL)
56 {
57 }
58 
60  :
61  ossimRpcModel(rhs),
62  theDecimation(1.0),
63  theProductXmlFile(rhs.theProductXmlFile)
64 {
65 
66 }
67 
68 
69 //*****************************************************************************
70 // CONSTRUCTOR: ossimRadarSat2RPCModel
71 //
72 // Constructs given filename for RS2 product.xml file
73 //
74 //*****************************************************************************
75 
77  :ossimRpcModel(), theDecimation(1.0)
78 {
79 
80  // Open the XML file, and read the RPC values in.
81  if (!open(RS2File))
82  {
84  << "DEBUG ossimRadarSat2RPCModel::ossimRadarSat2RPCModel(RS2File): Unable to parse file " << RS2File
85  << std::endl;
86  }
87 
88 }
89 
91 {
92 }
93 
95 {
96  return ossimString("ossimRadarSat2RPCModel");
97 }
98 
99 // ------ DUPLICATE RS2 MODEL OBJECT ----------
100 
102 {
103  return new ossimRadarSat2RPCModel(*this);
104 }
105 
107 {
108  static const char MODULE[] = "ossimRadarSat2RPCModel::open";
109 
110  if (traceDebug())
111  {
112  ossimNotify(ossimNotifyLevel_DEBUG)<< MODULE << " entered...\n";
113  }
114 
115  bool result = false;
116 
117  // Get the xml file.
118  ossimFilename xmlFile;
119 
120  if (file.ext().downcase() == "xml")
121  {
122  xmlFile = file;
123  }
124  else if (file.isFile())
125  {
126  xmlFile = file.expand().path().dirCat("product.xml");
127  }
128 
129  if (traceDebug())
130  {
132  << "product xml file: " << xmlFile << "\n";
133  }
134 
135  if ( xmlFile.exists() )
136  {
137  //---
138  // Instantiate the XML parser:
139  //---
140  ossimXmlDocument* xdoc = new ossimXmlDocument();
141  if ( xdoc->openFile(xmlFile) )
142  {
144 
145  result = rsDoc.isRadarSat2(xdoc);
146 
147  if (result)
148  {
149  if (traceDebug())
150  {
152  << "isRadarSat2...\n";
153  ossimString s;
154  if ( rsDoc.getBeamModeMnemonic(xdoc, s) )
155  {
157  << "beam_mode_mnemonic: " << s << "\n";
158  }
159  if ( rsDoc.getAcquisitionType(xdoc, s) )
160  {
162  << "acquisition_type: " << s << "\n";
163  }
164  }
165 
166  // Set the base class number of lines and samples
167  result = rsDoc.initImageSize(xdoc, theImageSize);
168 
169 
170  //---
171  // Fetch Image Size:
172  //---
173 
176 
177 
178  //***
179  // Assign the bounding image space rectangle:
180  //***
181 
182  if (result)
183  {
184  // Set the base class clip rect.
186  0, 0,
188  }
189 
190  // Set the sub image offset. tmp hard coded (drb).
191  theSubImageOffset.x = 0.0;
192  theSubImageOffset.y = 0.0;
193 
194  // Set the image id.
195  if (result)
196  {
197  result = rsDoc.getImageId(xdoc, theImageID);
198  }
199 
200  // Set the sensor ID.
201  if (result)
202  {
203  result = rsDoc.getSatellite(xdoc, theSensorID);
204  }
205 
206  // Set the base class gsd:
207  result = rsDoc.initGsd(xdoc, theGSD);
208  if (result)
209  {
210  theMeanGSD = (theGSD.x + theGSD.y)/2.0;
211  }
212 
213 
214  }
215 
216  thePolyType = B;
217 
218 
219  RPCModel model;
220  model = rsDoc.getRpcData(xdoc);
221 
222 
223  theBiasError = model.biasError;
224  theRandError = model.randomError;
225  theLineOffset = model.lineOffset;
226  theSampOffset = model.pixelOffset;
229  theHgtOffset = model.heightOffset;
230  theLineScale = model.lineScale;
231  theSampScale = model.pixelScale;
232  theLatScale = model.latitudeScale;
233  theLonScale = model.longitudeScale;
234  theHgtScale = model.heightScale;
235 
236 
237  if (traceDebug())
238  {
240  << "All parameters RPC : "
241  << theBiasError << ", "
242  << theRandError << ", "
243  << theLineOffset << ", "
244  << theSampOffset << ", "
245  << theLatOffset << ", "
246  << theLonOffset << ", "
247  << theHgtOffset << ", "
248  << theLineScale << ", "
249  << theSampScale << ", "
250  << theLatScale << ", "
251  << theLonScale << ", "
252  << theHgtScale << ", " << std::endl;
253  }
254 
255  // Parse coefficients:
256  ossim_uint32 i;
257 
258  for (i=0; i<20; ++i)
259  {
260 
265  }
266 
267  // Assign other data members to default values:
269  theRandError*theRandError); // meters
270 
271 
272 
273 
274  } // matches: if ( xdoc->openFile(xmlFile) )
275 
276  delete xdoc;
277  xdoc = 0;
278 
279  } // matches: if ( xmlFile.exists() )
280 
281  if (result)
282  {
283  theProductXmlFile = xmlFile;
284  }
285  else
286  {
288  }
289 
290  if (result)
291  {
292  theProductXmlFile = xmlFile;
293  }
294  else
295  {
297  }
298 
299  if (result)
300  {
301  // Assign the ossimSensorModel::theBoundGndPolygon
302  ossimGpt ul;
303  ossimGpt ur;
304  ossimGpt lr;
305  ossimGpt ll;
310  setGroundRect(ul, ur, lr, ll); // ossimSensorModel method.
311  }
312 
313  if (traceDebug())
314  {
316  << MODULE << " exit status = " << (result?"true":"false\n")
317  << std::endl;
318  }
319 
320 
321 
322  //---
323  // Get the decimation if any from the header "IMAG" field.
324  //
325  // Look for string like:
326  // "/2" = 1/2
327  // "/4 = 1/4
328  // ...
329  // "/16 = 1/16
330  // If it is full resolution it should be "1.0"
331  //---
332 
333  theDecimation = 1.0;
334 
335 
336 
337  //***
338  // Assign other data members:
339  //***
340  thePolyType = B; // This may not be true for early RPC imagery
346 
347 
348  //---
349  // Assign the bounding ground polygon:
350  //
351  // NOTE: We will use the base ossimRpcModel for transformation since all
352  // of our calls are in full image space (not decimated).
353  //---
354 
355  ossimGpt v0, v1, v2, v3;
356  ossimDpt ip0 (0.0, 0.0);
358  ossimDpt ip1 (theImageSize.samp-1.0, 0.0);
360  ossimDpt ip2 (theImageSize.samp-1.0, theImageSize.line-1.0);
362  ossimDpt ip3 (0.0, theImageSize.line-1.0);
364 
366  = ossimPolygon (ossimDpt(v0), ossimDpt(v1), ossimDpt(v2), ossimDpt(v3));
367 
368  updateModel();
369 
370  // Set the ground reference point.
372  theHgtOffset,
373  theRefGndPt);
374 
376  {
377  if (traceDebug())
378  {
380  << "ossimNitfRpcModel::ossimNitfRpcModel DEBUG:"
381  << "\nGround Reference Point not valid."
382  << " Aborting with error..."
383  << std::endl;
384  }
385  setErrorStatus();
386  return false;
387  }
388 
389 
390  return true;
391 }
392 
393 
395  ossimDpt& image_point) const
396 {
397  // Get the full res (not decimated) point.
398  ossimRpcModel::worldToLineSample(world_point, image_point);
399 
400  // Apply decimation.
401  image_point.x = image_point.x * theDecimation;
402  image_point.y = image_point.y * theDecimation;
403 }
404 
406  const ossimDpt& image_point,
407  const double& heightEllipsoid,
408  ossimGpt& worldPoint) const
409 {
410 
411  // Convert image point to full res (not decimated) point.
412  ossimDpt pt;
413  pt.x = image_point.x / theDecimation;
414  pt.y = image_point.y / theDecimation;
415 
416  // Call base...
417  ossimRpcModel::lineSampleHeightToWorld(pt, heightEllipsoid, worldPoint);
418 }
419 
421 {
422  // Capture the original flags.
423  std::ios_base::fmtflags f = out.flags();
424 
426 
427  // Reset flags.
428  out.setf(f);
429 
430  return out;
431 }
432 
434  const char *prefix)
435 {
436 
437  // sensor frequencies
438  const char* central_freq_str = kwl.find(prefix,"central_freq");
439  double central_freq = 0.0;
440  if (central_freq_str)
441  {
442  central_freq = ossimString::toDouble(central_freq_str);
443  }
444  const char* fr_str = kwl.find(prefix,"fr");
445  double fr = 0.0;
446  if (fr_str)
447  {
448  fr = ossimString::toDouble(fr_str);
449  }
450  const char* fa_str = kwl.find(prefix,"fa");
451  double fa = 0.0;
452  if (fa_str)
453  {
454  fa = ossimString::toDouble(fa_str);
455  }
456 
457  //number of different looks
458  const char* n_azilok_str = kwl.find(prefix,"n_azilok");
459  double n_azilok = 0.0;
460  if (n_azilok_str)
461  {
462  n_azilok = ossimString::toDouble(n_azilok_str);
463  }
464  const char* n_rnglok_str = kwl.find(prefix,"n_rnglok");
465  double n_rnglok = 0.0;
466  if (n_rnglok_str)
467  {
468  n_rnglok = ossimString::toDouble(n_rnglok_str);
469  }
470 
471  //ellipsoid parameters
472  const char* ellip_maj_str = kwl.find(prefix,"ellip_maj");
473  double ellip_maj = 0.0;
474  if (ellip_maj_str)
475  {
476  ellip_maj = ossimString::toDouble(ellip_maj_str) * 1000.0;// km -> m
477  }
478  const char* ellip_min_str = kwl.find(prefix,"ellip_min");
479  double ellip_min = 0.0;
480  if (ellip_min_str)
481  {
482  ellip_min = ossimString::toDouble(ellip_min_str) * 1000.0;// km -> m
483  }
484 
485  if(_sensor != 0)
486  {
487  delete _sensor;
488  }
489 
490  _sensor = new SensorParams();
491 
492  const char* lineTimeOrdering_str = kwl.find(prefix,"lineTimeOrdering");
493  std::string lineTimeOrdering(lineTimeOrdering_str) ;
494  const char* pixelTimeOrdering_str = kwl.find(prefix,"pixelTimeOrdering");
495  std::string pixelTimeOrdering(pixelTimeOrdering_str) ;
496  if (pixelTimeOrdering == "Increasing") _sensor->set_col_direction(1);
497  else _sensor->set_col_direction(- 1);
498  if (lineTimeOrdering == "Increasing") _sensor->set_lin_direction(1);
499  else _sensor->set_lin_direction(- 1);
500 
501  const char* lookDirection_str = kwl.find(prefix,"lookDirection");
502  std::string lookDirection(lookDirection_str) ;
503  if ((lookDirection == "Right")||(lookDirection == "RIGHT")) _sensor->set_sightDirection(SensorParams::Right) ;
505 
506  _sensor->set_sf(fr);
507  const double CLUM = 2.99792458e+8 ;
508  double wave_length = CLUM / central_freq ;
509  _sensor->set_rwl(wave_length);
510  _sensor->set_nAzimuthLook(n_azilok);
511  _sensor->set_nRangeLook(n_rnglok);
512 
513  // fa is the processing PRF
514  _sensor->set_prf(fa * n_azilok);
515 
516  _sensor->set_semiMajorAxis(ellip_maj) ;
517  _sensor->set_semiMinorAxis(ellip_min) ;
518 
519  return true;
520 }
521 
523  const ossimXmlDocument* xdoc, const ossimRadarSat2ProductDoc& rsDoc)
524 {
525  static const char MODULE[] = "ossimRadarSat2RPCModel::initSensorParams";
526 
527  if (traceDebug())
528  {
529  ossimNotify(ossimNotifyLevel_DEBUG)<< MODULE << " entered...\n";
530  }
531 
532  if (_sensor )
533  {
534  delete _sensor;
535  }
536  _sensor = new SensorParams();
537 
538  bool result = rsDoc.initSensorParams(xdoc, _sensor);
539 
540  if (!result)
541  {
542  delete _sensor;
543  _sensor = 0;
544  }
545 
546  if (traceDebug())
547  {
549  << MODULE << " exit status = " << (result?"true":"false\n")
550  << std::endl;
551  }
552 
553  return result;
554 }
555 
557  const char* prefix) const
558 {
559  static const char MODULE[] = "ossimRadarSat2RPCModel::saveState";
560 
561  if (traceDebug())
562  {
563  ossimNotify(ossimNotifyLevel_DEBUG)<< MODULE << " entered...\n";
564  }
565 
566  bool result = true;
567 
568  kwl.add(prefix, "decimation", theDecimation);
569 
570  // Save our state:
571  kwl.add(prefix, PRODUCT_XML_FILE_KW, theProductXmlFile.c_str());
572 
573  if (result)
574  {
575  // Call base save state:
576  result = ossimRpcModel::saveState(kwl, prefix);
577  }
578 
579  if (traceDebug())
580  {
582  << MODULE << " exit status = " << (result?"true":"false\n")
583  << std::endl;
584  }
585 
586  return result;
587 }
588 
589 
591  const char *prefix)
592 {
593  static const char MODULE[] = "ossimRadarSat2RPCModel::loadState";
594 
595  if (traceDebug())
596  {
597  ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " entered...\n";
598  }
599 
600  const char* lookup = 0;
601  ossimString s;
602 
603  // Check the type first.
604  lookup = kwl.find(prefix, ossimKeywordNames::TYPE_KW);
605  if (lookup)
606  {
607  s = lookup;
608  if (s != getClassName())
609  {
610  return false;
611  }
612  }
613 
614  // Get the product.xml file name.
615  lookup = kwl.find(prefix, PRODUCT_XML_FILE_KW);
616  if (lookup)
617  {
618  theProductXmlFile = lookup;
619 
620  // See if caller wants to load from xml vice keyword list.
621  lookup = kwl.find(prefix, LOAD_FROM_PRODUCT_FILE_KW);
622  if (lookup)
623  {
624  s = lookup;
625  if ( s.toBool() )
626  {
627  // Loading from product.xml file.
628  return open(theProductXmlFile);
629  }
630  }
631  }
632 
633 
634  // Call base.
635  bool result = ossimRpcModel::loadState(kwl, prefix);
636 
637  // Lookup decimation.
638  const char* value = kwl.find(prefix, "decimation");
639  if (value)
640  {
642  if (theDecimation <= 0.0)
643  {
644  // Do not allow negative or "0.0"(divide by zero).
645  theDecimation = 1.0;
646  }
647  }
648 
649 
650  //---
651  // Temp: This must be cleared or you end up with a bounding rect of all
652  // zero's.
653  //---
655 
656  if (traceDebug())
657  {
659  << MODULE << " exit status = " << (result?"true":"false\n")
660  << std::endl;
661  }
662 
663  return result;
664 }
665 }
double theSampOffset
ossimString theSensorID
PolynomialType thePolyType
virtual void worldToLineSample(const ossimGpt &world_point, ossimDpt &image_point) const
worldToLineSample() Overrides base class implementation.
double theSampNumCoef[20]
void set_sightDirection(SightDirection sight)
Definition: SensorParams.h:93
virtual bool saveState(ossimKeywordlist &kwl, const char *prefix=0) const
Method to save object state to a keyword list.
virtual std::ostream & print(std::ostream &out) const
static const ossimFilename NIL
This was taken from Wx widgets for performing touch and access date stamps.
Definition: ossimFilename.h:40
void set_rwl(double rwl)
Definition: SensorParams.h:83
RTTI_DEF1(ossimAlosPalsarModel, "ossimAlosPalsarModel", ossimGeometricSarSensorModel)
Represents serializable keyword/value map.
bool isLonNan() const
Definition: ossimGpt.h:140
virtual void lineSampleHeightToWorld(const ossimDpt &image_point, const double &heightEllipsoid, ossimGpt &worldPoint) const
lineSampleHeightToWorld() Backs out decimation of image_point (if needed) then calls: ossimRpcModel::...
const char * find(const char *key) const
ossimString theImageID
double samp
Definition: ossimDpt.h:164
ossimFilename expand() const
Method to do file name expansion.
const ossimDpt & ul() const
Definition: ossimDrect.h:339
double y
Definition: ossimDpt.h:165
void set_lin_direction(int dir)
Definition: SensorParams.h:128
virtual void updateModel()
Class to encapsulate parsing RadarSat2 product.xml file.
ossim_float64 hgt
Height in meters above the ellipsiod.
Definition: ossimGpt.h:274
vector< double > pixelNumeratorCoefficients
bool getSatellite(const ossimXmlDocument *xdoc, ossimString &s) const
This class handles the sensor parameters.
Definition: SensorParams.h:29
virtual void lineSampleToWorld(const ossimDpt &image_point, ossimGpt &world_point) const
double theLonScale
bool isLatNan() const
Definition: ossimGpt.h:139
double theLineScale
static const char * TYPE_KW
void set_semiMinorAxis(double value)
Definition: SensorParams.h:158
double theSampDenCoef[20]
double theLineNumCoef[20]
double theLatOffset
void add(const char *prefix, const ossimKeywordlist &kwl, bool overwrite=true)
virtual std::ostream & print(std::ostream &out) const
print() Extends base-class implementation.
ossimDpt theSubImageOffset
bool getAcquisitionType(const ossimXmlDocument *xdoc, ossimString &s) const
/product/sourceAttributes/radarParameters/acquisitionType
double theHgtOffset
double theLonOffset
double line
Definition: ossimDpt.h:165
bool isRadarSat2(const ossimXmlDocument *xdoc) const
Checks for node /product/sourceAttributes/satellite containing RADARSAT-2.
double theRandError
bool openFile(const ossimFilename &filename)
bool initSensorParams(const ossimXmlDocument *xdoc, SensorParams *sp) const
Method to initialize SensorParams object from RadarSat "product.xml" file.
bool exists() const
ossim_float64 lon
Definition: ossimGpt.h:266
ossim_float64 theNominalPosError
double theLatScale
virtual bool saveState(ossimKeywordlist &kwl, const char *prefix=0) const
saveState Fulfills ossimObject base-class pure virtuals.
bool toBool() const
String to numeric methods.
bool initGsd(const ossimXmlDocument *xdoc, ossimDpt &gsd) const
Method to initialize gsd from RadarSat "product.xml" file.
unsigned int ossim_uint32
ossimPolygon theBoundGndPolygon
bool initSensorParams(const ossimXmlDocument *xdoc, const ossimRadarSat2ProductDoc &rsDoc)
double toDouble() const
ossim_float64 toFloat64() const
virtual void lineSampleHeightToWorld(const ossimDpt &image_point, const double &heightEllipsoid, ossimGpt &worldPoint) const
bool isFile() const
void set_semiMajorAxis(double value)
Definition: SensorParams.h:153
virtual ossimString getClassName() const
Method to return the class name.
static ossimString downcase(const ossimString &aString)
Definition: ossimString.cpp:48
virtual bool loadState(const ossimKeywordlist &kwl, const char *prefix=0)
Method to the load (recreate) the state of the object from a keyword list.
bool open(const ossimFilename &file)
Method to parse an nitf file and initialize model.
void set_nRangeLook(double look)
Definition: SensorParams.h:138
vector< double > lineNumeratorCoefficients
vector< double > pixelDenominatorCoefficients
ossimDrect theImageClipRect
bool getBeamModeMnemonic(const ossimXmlDocument *xdoc, ossimString &s) const
/product/sourceAttributes/beamModeMnemonic
ossim_int32 samp
Definition: ossimIpt.h:141
This class allows for direct localisation and indirect localisation using the RadarSat2 sensor model...
vector< double > lineDenominatorCoefficients
ossim_int32 y
Definition: ossimIpt.h:142
bool initImageSize(const ossimXmlDocument *xdoc, ossimIpt &imageSize) const
Method to initialize image size from RadarSat "product.xml" file.
void setGroundRect(const ossimGpt &ul, const ossimGpt &ur, const ossimGpt &lr, const ossimGpt &ll)
const ossimDpt & ur() const
Definition: ossimDrect.h:340
double x
Definition: ossimDpt.h:164
ossimFilename dirCat(const ossimFilename &file) const
const char * c_str() const
Returns a pointer to a null-terminated array of characters representing the string&#39;s contents...
Definition: ossimString.h:396
bool InitSensorParams(const ossimKeywordlist &kwl, const char *prefix)
void set_nAzimuthLook(double look)
Definition: SensorParams.h:133
double theSampScale
ossim_int32 line
Definition: ossimIpt.h:142
ossimString ext() const
ossim_int32 x
Definition: ossimIpt.h:141
RPCModel getRpcData(const ossimXmlDocument *xdoc) const
const ossimDpt & ll() const
Definition: ossimDrect.h:342
ossim_float64 lat
Definition: ossimGpt.h:265
virtual bool loadState(const ossimKeywordlist &kwl, const char *prefix=0)
loadState Fulfills ossimObject base-class pure virtuals.
void set_prf(double prf)
Definition: SensorParams.h:73
double theLineDenCoef[20]
ossim_float64 theDecimation
Stored from header field "IMAG".
void set_col_direction(int dir)
Definition: SensorParams.h:123
double theLineOffset
const ossimDpt & lr() const
Definition: ossimDrect.h:341
double theHgtScale
double theBiasError
error
void set_sf(double sf)
Definition: SensorParams.h:78
ossimFilename path() const
virtual ossimObject * dup() const
Returns pointer to a new instance, copy of this.
bool getImageId(const ossimXmlDocument *xdoc, ossimString &s) const
OSSIMDLLEXPORT std::ostream & ossimNotify(ossimNotifyLevel level=ossimNotifyLevel_WARN)
virtual void worldToLineSample(const ossimGpt &world_point, ossimDpt &image_point) const
worldToLineSample() Calls ossimRpcModel::worldToLineSample(), then applies (if needed) decimation...
ossim_float64 theMeanGSD
std::basic_ostream< char > ostream
Base class for char output streams.
Definition: ossimIosFwd.h:23