OSSIM - Open Source Software Image Map  Version 1.9.0 (20180803)
ossimAlphaSensorSupportData.cpp
Go to the documentation of this file.
9 #include <sstream>
10 
11 static ossimTrace traceDebug("ossimAlphaSensorSupportData:debug");
12 
13 
15  : m_isHSI(false),
16  m_sensorType(),
17  m_imageSize(),
18  m_rollBias(ossim::nan()),
19  m_pitchBias(ossim::nan()),
20  m_headingBias(ossim::nan()),
21  m_fov(ossim::nan()),
22  m_slitRot(ossim::nan()),
23  m_imgLine(),
24  m_roll(),
25  m_pitch(),
26  m_heading(),
27  m_lon(),
28  m_lat(),
29  m_alt(),
30  m_scanAng(),
31  m_rollPolyCoef(),
32  m_pitchPolyCoef(),
33  m_headingPolyCoef(),
34  m_lonPolyCoef(),
35  m_altPolyCoef(),
36  m_scanAngPolyCoef()
37 {
38  reset();
39 }
40 
42 {
44 }
45 
46 
48 {
49  bool readOK = false;
50 
51  // Read ENVI hdr file
52  ossimEnviHeader hdr;
53  if ( hdr.open(hdrFile) )
54  {
55  readOK= readSupportFiles( hdr );
56  }
57  return readOK;
58 }
59 
61 {
62  bool readOK = readHdrFile(hdr);
63 
64  ossimFilename txtFile = hdr.getFile();
65 
66  if ( readOK )
67  {
68  // Derive associated insgps.txt file name
69  if (m_isHSI)
70  {
71  // HSI:
72  // Associated file is located in /NavData, sub-directory of current container
73  // example:
74  // .hdr = "/data/AH/2012-06-15_20-00-29/HSI/Scan_00002/2012-06-15_20-00-29.HSI.Scan_00002.scene.corrected.hsi.hdr"
75  // .txt = "/data/AH/2012-06-15_20-00-29/HSI/Scan_00002/NavData/2012-06-15_20-00-29.HSI.Scan_00002.scene.insgps.txt"
76  // txtFile.insert(hdr.getFile().find_last_of('/'), "/NavData");
77  // txtFile.gsub("corrected.hsi.hdr", "insgps.txt");
78 
79  ossimFilename navDir = hdr.getFile().path();
80  navDir = navDir.dirCat("NavData");
81  if ( navDir.exists() )
82  {
83  txtFile = navDir.dirCat( hdr.getFile().file() );
84  txtFile.gsub("corrected.hsi.hdr", "insgps.txt");
85  }
86  else
87  {
88  //--
89  // Example header and inertial nav support(INS) data file paths:
90  //
91  // Header: /data/20131113/hsi/cal/001_001_hsi_cal_001.hsi.hdr
92  // INS: /data/20131113/hsi/nav/001_001_hsi_cal_001.txt
93  //---
94 
95  // Expand header file out to absolute path:
96  txtFile = hdr.getFile().expand();
97 
98  // Substitute the "cal" directory with "nav".
99  txtFile.gsub("cal/", "nav/");
100 
101  // Substitute the "hsi.hdr" directory with "txt".
102  txtFile.gsub("hsi.hdr", "txt");
103  }
104  }
105  else
106  {
107  // HRI:
108  // Associated file is located in ../NavData, parallel to current container
109  // There is one insgps.txt file common to multiple hdr files
110  // example:
111  // .hdr = "/data/AH/2012-06-15_20-00-29/HRI/HRI_2/2012-06-15_20-00-29.HRI_2.Strip_00004.corrected.hri.hdr"
112  // .txt = "/data/AH/2012-06-15_20-00-29/HRI/NavData/2012-06-15_20-00-29.HRI.Strip_00004.insgps.txt"
113 
114  // Replaced: 29 July 2013 (drb)
115  // txtFile = hdr.getFile().path();
116  // if ( txtFile.empty() )
117  // {
118  // txtFile = txtFile.dirCat("../NavData");
119  // }
120  // else
121  // {
122  // txtFile.replace(txtFile.find("HRI_"), 5, "NavData");
123  // }
124  // txtFile = txtFile.dirCat( hdr.getFile().file() );
125  // txtFile.replace(txtFile.find("HRI_"), 5, "HRI");
126  // txtFile.gsub("corrected.hri.hdr", "insgps.txt");
127  //
128  // with:
129 
130  ossimFilename navDir = hdr.getFile().path();
131  if ( navDir.empty() )
132  {
133  navDir = navDir.dirCat("../NavData");
134  }
135  else
136  {
137  std::string::size_type pos = navDir.find("HRI_");
138  if(pos!=std::string::npos)
139  {
140  navDir = navDir.replace(pos, 5, "NavData");
141  }
142  }
143  if ( navDir.exists() )
144  {
145  txtFile = navDir.dirCat( hdr.getFile().file() );
146  std::string::size_type pos = txtFile.find("HRI_");
147  if(pos!=std::string::npos)
148  {
149  txtFile.replace(pos, 5, "HRI");
150  }
151  txtFile.gsub("corrected.hri.hdr", "insgps.txt");
152  }
153  else
154  {
155  navDir = "../nav";
156  txtFile = navDir.dirCat( hdr.getFile().file() );
157  txtFile.gsub("hri.hdr", "txt");
158  }
159  }
160 
161  // Read .txt file
162  readOK = readInsGpsFile(txtFile);
163  }
164 
165  if (traceDebug())
166  {
168  << "ossimAlphaSensorSupportData::readSupportFiles DEBUG:"
169  << "\n hdrFile = " << hdr.getFile()
170  << "\n txtFile = " << txtFile
171  << std::endl;
172  }
173 
174  return readOK;
175 }
176 
178 {
179  bool result = false;
180  ossimEnviHeader hdr;
181  if ( hdr.open(hdrFile) )
182  {
183  result = readHdrFile( hdr );
184  }
185  return result;
186 }
187 
189 {
190  bool result = false;
191 
192  while( 1 )
193  {
194  // Required stuff will break from loop if not found/valid.
195 
196  m_sensorType = hdr.getSensorType();
197  if ( m_sensorType.empty() ) break;
198 
199  if ( m_sensorType == "Unknown" )
200  {
201  // Make an assumption from file name...
202  if ( hdr.getFile().file().contains( ossimString("HSI") ) )
203  {
204  m_sensorType = "ACES_YOGI-HSI";
205  }
206  else if ( hdr.getFile().file().contains( ossimString("HRI") ) )
207  {
208  m_sensorType = "ACES_YOGI-HRI2";
209  }
210  }
211 
212  if ( m_sensorType == "Unknown" )
213  {
214  break; // Get out...
215  }
216 
217  // Set the hsi flag:
218  if ( m_sensorType.contains("HSI") || (hdr.getBands() > 7 ) ) // arbitrary...
219  {
220  m_isHSI = true;
221  }
222  else
223  {
224  m_isHSI = false;
225  }
226 
227  m_imageSize.x = hdr.getSamples();
228  m_imageSize.y = hdr.getLines();
229  if ( !m_imageSize.x || !m_imageSize.y ) break;
230 
231  ossimString value;
232 
233  hdr.getValue("roll bias", value);
234  if ( value.size() )
235  {
237  }
238  else
239  {
240  break;
241  }
242 
243  hdr.getValue("pitch bias", value);
244  if ( value.size() )
245  {
247  }
248  else
249  {
250  break;
251  }
252 
253  hdr.getValue("heading bias", value);
254  if ( value.size() )
255  {
257  }
258  else
259  {
260  break;
261  }
262 
263  hdr.getValue("fpa fov deg", value);
264  if ( value.size() )
265  {
266  m_fov = ossimString::toDouble(value);
267  }
268  else
269  {
270  break;
271  }
272 
273  hdr.getValue("slit rotation deg", value);
274  if ( value.size() )
275  {
277  }
278  else
279  {
280  // Removed requirement. Missing in some support data and always 0 when present.
281  if ( traceDebug() )
282  {
284  << "Missing: \"slit rotation deg\"\n";
285  }
286  }
287 
288  if (traceDebug())
289  {
291  << "ossimAlphaSensorSupportData::readHdrFile DEBUG:"
292  << "\n getSensorType = " << m_sensorType
293  << "\n getSamples = " << m_imageSize.x
294  << "\n getLines = " << m_imageSize.y
295  << "\n roll bias = " << m_rollBias
296  << "\n pitch bias = " << m_pitchBias
297  << "\n heading bias = " << m_headingBias
298  << "\n fpa fov deg = " << m_fov
299  << "\n slit rotation deg = " << m_slitRot
300  << "\n";
301  }
302 
303  // Last two lines of while forever. If we get here, set status true and break out.
304  result = true;
305  break;
306  }
307 
308  return result;
309 
310 } // End: bool ossimAlphaSensorSupportData::readHdrFile(const ossimEnviHeader& )
311 
313 {
314  bool result = true;
315 
316  static const char M[] = "ossimAlphaSensorSupportData::readInsGpsFile";
317 
318  if (traceDebug())
319  {
321  << M << " entered:\n" << "file: " << file << "\n";
322  }
323 
324  std::shared_ptr<ossim::istream> in = ossim::StreamFactoryRegistry::instance()->
325  createIstream( file, std::ios_base::in);
326 
327  if ( in && in->good() )
328  {
329  ossim_float64 inum;
330  ossim_float64 roll;
331  ossim_float64 pitch;
332  ossim_float64 heading;
333  ossim_float64 lon;
334  ossim_float64 lat;
335  ossim_float64 alt;
336  ossim_float64 scanAng;
337  int res;
338  int frm;
339  const ossim_float64 BOGUS = -99999.0; // To detect read error/missing value.
340  ossim_float64 timeCode = BOGUS;
341 
342  std::vector< ossim_uint32 > lines;
343 
344  if (traceDebug())
345  {
347  << "ossimAlphaSensorSupportData::readInsGpsFile DEBUG:" << std::endl;
348  ossimNotify(ossimNotifyLevel_DEBUG)<<std::setprecision(8);
349  ossimNotify(ossimNotifyLevel_DEBUG)<<std::setiosflags(std::ios_base::scientific);
350 
351  }
352 
353  // Format: line,roll,pitch,heading,lon,lat,alt,scanAngle,reserved,frame,time
354 
355  // Check the first line. Some data has a phantom line, some starts with good data.
356  std::string line1;
357  std::getline( *in, line1 );
358  ossim_uint32 fields = 0;
359  if ( line1.size() )
360  {
361  std::string s;
362  std::istringstream tmpStr( line1 );
363  while ( !tmpStr.eof() )
364  {
365  tmpStr >> s;
366  if ( s.size() )
367  {
368  ++fields;
369  s.clear();
370  }
371  }
372  if ( fields == 11 )
373  {
374  // First line is valid.
375  in->seekg( 0, std::ios_base::beg );
376  }
377  }
378 
379  while( !in->eof() )
380  {
381  // To detect read error/missing value. Check eof was missing last line.
382  timeCode = BOGUS;
383 
384  *in >> inum >> roll >> pitch >> heading >> lon >> lat
385  >> alt >> scanAng >> res >> frm >> timeCode;
386 
387  // if(!in.eof())
388  if ( timeCode != BOGUS )
389  {
390  lines.push_back(inum);
391  m_roll.push_back(roll);
392  m_pitch.push_back(pitch);
393  m_heading.push_back(heading);
394  m_lon.push_back(lon);
395  m_lat.push_back(lat);
396  m_alt.push_back(alt);
397  m_scanAng.push_back(scanAng);
398  }
399  }
400 
401  // Make sure we have a value per line
402  if( (lines.size() < m_imageSize.y) || (lines.size() < 10) )
403  {
404  return false;
405  }
406 
407  // Load independent variable (line number, referenced to first line)
408  vector< ossimPolynom< ossim_float64 , 1 >::VAR_TUPLE >::iterator pit;
409  m_imgLine.resize(lines.size());
410  int j;
411  for (pit=m_imgLine.begin(), j=0; pit!=m_imgLine.end(); ++pit,++j)
412  {
413  pit->push_back(lines[j]-lines[0]);
414  }
415 
416  // Dependent variable solutions follow...
417  double rms=0.0;
418 
419  // Exponent sets
420  std::vector< ossimPolynom<ossim_float64,1>::EXPT_SET > expSet;
421  expSet.resize(MAX_TERMS);
423  for (int numExp=1; numExp<=MAX_TERMS; ++numExp)
424  {
425  for(int o=0; o<numExp ; ++o)
426  {
427  et[0]=o;
428  expSet[numExp-1].insert(et);
429  }
430  }
431 
432  // Polynomial classes
433  // scanAngle
435  // orientation angles (roll, pitch, heading)
439  // position (longitude, latitude, altitude)
443 
444  // Solve for polynomial coefficients
445  if (m_isHSI)
446  {
447  result = saPoly.SLSfit(expSet[SCAN_ANGLE_DEG], m_imgLine, m_scanAng, &rms);
448  if (traceDebug())
449  {
451  << "\n SA poly deg, rms error = "
452  << SCAN_ANGLE_DEG << ", " << ossim::radiansToDegrees(rms) << " deg\n";
453  }
454  }
455  if (result)
456  {
457  result = rPoly.SLSfit(expSet[ROLL_DEG], m_imgLine, m_roll, &rms);
458  if (traceDebug())
459  {
461  << "\n R poly deg, rms error = "
462  << ROLL_DEG << ", " << ossim::radiansToDegrees(rms) << " deg\n";
463  }
464 
465  if (result)
466  {
467  result = pPoly.SLSfit(expSet[PITCH_DEG], m_imgLine, m_pitch, &rms);
468  if (traceDebug())
469  {
471  << "\n P poly deg, rms error = "
472  << PITCH_DEG << ", " << ossim::radiansToDegrees(rms) << " deg\n";
473  }
474 
475  if (result)
476  {
477  result = hPoly.SLSfit(expSet[HEADING_DEG], m_imgLine, m_heading, &rms);
478  if (traceDebug())
479  {
481  << "\n H poly deg, rms error = "
482  << HEADING_DEG << ", " << ossim::radiansToDegrees(rms) << " deg\n";
483  }
484 
485  if (result)
486  {
487  result = lonPoly.SLSfit(expSet[LON_DEG], m_imgLine, m_lon, &rms);
488  if (traceDebug())
489  {
491  << "\n Lon poly deg, rms error = "
492  << LON_DEG << ", " << ossim::radiansToDegrees(rms) << " deg\n";
493  }
494 
495  if (result)
496  {
497  result = latPoly.SLSfit(expSet[LAT_DEG], m_imgLine, m_lat, &rms);
498  if (traceDebug())
499  {
501  << "\n Lat poly deg, rms error = "
502  << LAT_DEG << ", " << ossim::radiansToDegrees(rms) << " deg\n";
503  }
504 
505  if (result)
506  {
507  result = altPoly.SLSfit(expSet[ALT_DEG], m_imgLine, m_alt, &rms);
508  if (traceDebug())
509  {
511  << "\n Alt poly deg, rms error = "
512  << ALT_DEG << ", " << rms << " mtr" << std::endl;
513  }
514  }
515  }
516  }
517  }
518  }
519  }
520 
521  if (result)
522  {
523  // Save coefficients
525  for (it = rPoly.getMonoms().begin(); it != rPoly.getMonoms().end() ; ++it )
526  {
527  m_rollPolyCoef.push_back(it->second);
528  }
529  for (it = pPoly.getMonoms().begin(); it != pPoly.getMonoms().end() ; ++it )
530  {
531  m_pitchPolyCoef.push_back(it->second);
532  }
533  for (it = hPoly.getMonoms().begin(); it != hPoly.getMonoms().end() ; ++it )
534  {
535  m_headingPolyCoef.push_back(it->second);
536  }
537  for (it = lonPoly.getMonoms().begin(); it != lonPoly.getMonoms().end() ; ++it )
538  {
539  m_lonPolyCoef.push_back(it->second);
540  }
541  for (it = latPoly.getMonoms().begin(); it != latPoly.getMonoms().end() ; ++it )
542  {
543  m_latPolyCoef.push_back(it->second);
544  }
545  for (it = altPoly.getMonoms().begin(); it != altPoly.getMonoms().end() ; ++it )
546  {
547  m_altPolyCoef.push_back(it->second);
548  }
549  if (m_isHSI)
550  {
551  for (it = saPoly.getMonoms().begin(); it != saPoly.getMonoms().end() ; ++it )
552  {
553  m_scanAngPolyCoef.push_back(it->second);
554  }
555  }
556  else
557  {
558  m_scanAngPolyCoef.push_back(0.0);
559  }
560  }
561 
562 
563  if (traceDebug())
564  {
565  if (result)
566  {
567  vector<ossim_float64> inp(1);
568  inp[0] = 510.0;
569  ossimNotify(ossimNotifyLevel_DEBUG) << "\n Test eval line number = " << inp[0] << endl;
570  if (m_isHSI)
571  {
573  ossim_float64 sa = saPoly.eval(inp);
574  ossimNotify(ossimNotifyLevel_DEBUG)<<"\n sa="<<sa<<endl;
575  }
577  ossim_float64 rr = rPoly.eval(inp);
578  ossimNotify(ossimNotifyLevel_DEBUG)<<"\n r="<<rr<<endl;
579 
581  ossim_float64 pp = pPoly.eval(inp);
582  ossimNotify(ossimNotifyLevel_DEBUG)<<"\n p="<<pp<<endl;
583 
585  ossim_float64 hh = hPoly.eval(inp);
586  ossimNotify(ossimNotifyLevel_DEBUG)<<"\n h="<<hh<<endl;
587 
589  ossim_float64 lon = lonPoly.eval(inp);
590  ossimNotify(ossimNotifyLevel_DEBUG)<<"\n lon="<<lon<<endl;
591 
593  ossim_float64 lat = latPoly.eval(inp);
594  ossimNotify(ossimNotifyLevel_DEBUG)<<"\n lat="<<lat<<endl;
595 
597  ossim_float64 alt = altPoly.eval(inp);
598  ossimNotify(ossimNotifyLevel_DEBUG)<<"\n alt="<<alt<<endl;
599  }
600  else
601  {
603  << " ...polynomial solution error for file: " << file << std::endl;
604  }
605  }
606  }
607  else
608  {
609  result = false;
610  if (traceDebug())
611  {
613  << "Could not open: " << file << "\n";
614  }
615  }
616 
617  if (traceDebug())
618  {
620  << M << " exit status = " << ( result ? "true" : "false" ) << "\n";
621  }
622 
623  return result;
624 }
625 
627 {
628  return m_imageSize;
629 }
630 
632 {
633  return m_rollBias;
634 }
635 
637 {
638  return m_pitchBias;
639 }
640 
642 {
643  return m_headingBias;
644 }
645 
647 {
648  return m_fov;
649 }
650 
652 {
653  return m_slitRot;
654 }
655 
656 const std::vector< ossim_float64 >& ossimAlphaSensorSupportData::getRollPoly()const
657 {
658  return m_rollPolyCoef;
659 }
660 
661 const std::vector< ossim_float64 >& ossimAlphaSensorSupportData::getPitchPoly()const
662 {
663  return m_pitchPolyCoef;
664 }
665 
666 const std::vector< ossim_float64 >& ossimAlphaSensorSupportData::getHeadingPoly()const
667 {
668  return m_headingPolyCoef;
669 }
670 
671 const std::vector< ossim_float64 >& ossimAlphaSensorSupportData::getLonPoly()const
672 {
673  return m_lonPolyCoef;
674 }
675 
676 const std::vector< ossim_float64 >& ossimAlphaSensorSupportData::getLatPoly()const
677 {
678  return m_latPolyCoef;
679 }
680 
681 const std::vector< ossim_float64 >& ossimAlphaSensorSupportData::getAltPoly()const
682 {
683  return m_altPolyCoef;
684 }
685 
686 const std::vector< ossim_float64 >& ossimAlphaSensorSupportData::getScanPoly()const
687 {
688  return m_scanAngPolyCoef;
689 }
690 
691 
692 // Hidden from use...
694 {
695 }
696 
698  const ossimAlphaSensorSupportData& /* src */)
699 {
700  return *this;
701 }
702 
virtual bool readSupportFiles(const ossimFilename &hdrFile)
std::vector< ossim_float64 > m_pitchPolyCoef
std::vector< ossim_float64 > m_alt
std::vector< ossim_float64 > m_headingPolyCoef
T eval(const VAR_TUPLE &v) const
evaluation : needs DIM values as input
Definition: ossimPolynom.h:219
const std::vector< ossim_float64 > & getLatPoly() const
virtual bool readHdrFile(const ossimFilename &hdrFile)
ossimFilename expand() const
Method to do file name expansion.
std::vector< ossim_float64 > m_heading
double nan()
Method to return ieee floating point double precision NAN.
Definition: ossimCommon.h:135
This code was derived from https://gist.github.com/mshockwave.
Definition: Barrier.h:8
const ossim_float64 & getSlitRot() const
double y
Definition: ossimDpt.h:165
template class for multivariate polynom algebra
Definition: ossimPolynom.h:38
const std::vector< ossim_float64 > & getLonPoly() const
bool contains(char aChar) const
Definition: ossimString.h:58
bool SLSfit(const EXPT_SET &expset, const std::vector< VAR_TUPLE > obs_input, const std::vector< T > obs_output, T *prms=NULL)
Standard least squares Modified version of LMSfit that uses standard NEWMAT inverse as alternative to...
Definition: ossimPolynom.h:700
const ossimFilename & getFile() const
const ossim_float64 & getFov() const
static StreamFactoryRegistry * instance()
std::istream & getline(std::istream &is, ossimString &str, char delim)
Definition: ossimString.h:916
std::vector< ossim_float64 > m_altPolyCoef
double radiansToDegrees(double x)
Definition: ossimCommon.h:257
bool open(const ossimFilename &file)
Opens an envi header.
double ossim_float64
ossim_uint32 getLines() const
bool exists() const
std::string::size_type size() const
Definition: ossimString.h:405
const std::vector< ossim_float64 > & getAltPoly() const
ossim_uint32 getBands() const
unsigned int ossim_uint32
double toDouble() const
const ossim_float64 & getHeadingBias() const
std::vector< ossim_float64 > m_pitch
std::vector< int > EXP_TUPLE
inner types
Definition: ossimPolynom.h:44
const MONOM_MAP & getMonoms() const
Definition: ossimPolynom.h:145
std::vector< ossim_float64 > m_lat
ossim_uint32 getSamples() const
std::vector< ossim_float64 > m_scanAngPolyCoef
std::vector< ossim_float64 > m_latPolyCoef
virtual bool readInsGpsFile(const ossimFilename &txtFile)
const ossim_float64 & getRollBias() const
std::vector< ossim_float64 > m_rollPolyCoef
std::string & replace(std::string::size_type pos, std::string::size_type n, const std::string &s)
Replaces a substring of *this with the string s.
Definition: ossimString.h:870
ossimString getSensorType() const
std::vector< ossimPolynom< ossim_float64, 1 >::VAR_TUPLE > m_imgLine
Class for reading and writing an ENVI (The Environment for Visualizing Images) header file...
double x
Definition: ossimDpt.h:164
ossimFilename dirCat(const ossimFilename &file) const
const std::vector< ossim_float64 > & getScanPoly() const
ossimAlphaSensorSupportData & operator=(const ossimAlphaSensorSupportData &src)
bool empty() const
Definition: ossimString.h:411
std::ostream & print(std::ostream &os) const
I/O.
Definition: ossimPolynom.h:370
bool getValue(const ossimString &key, ossimString &value) const
Gets value for key.
ossimFilename file() const
std::vector< ossim_float64 > m_lonPolyCoef
ossimString & gsub(const ossimString &searchKey, const ossimString &replacementValue, bool replaceAll=false)
Substitutes searchKey string with replacementValue and returns a reference to *this.
std::basic_istringstream< char > istringstream
Class for char input memory streams.
Definition: ossimIosFwd.h:32
const std::vector< ossim_float64 > & getPitchPoly() const
ossimFilename path() const
std::vector< ossim_float64 > m_lon
const std::vector< ossim_float64 > & getHeadingPoly() const
std::string::size_type find(const std::string &s, std::string::size_type pos=0) const
Searches for s as a substring of *this, beginning at character pos of *this.
Definition: ossimString.h:753
std::vector< ossim_float64 > m_roll
const ossim_float64 & getPitchBias() const
OSSIMDLLEXPORT std::ostream & ossimNotify(ossimNotifyLevel level=ossimNotifyLevel_WARN)
void makeNan()
Definition: ossimDpt.h:65
const std::vector< ossim_float64 > & getRollPoly() const
std::vector< ossim_float64 > m_scanAng