From ebef6e2afe3dc8ec34189217361369abee1d9d91 Mon Sep 17 00:00:00 2001 From: Emmanuel Christophe <emmanuel.christophe@nus.edu.sg> Date: Thu, 13 Aug 2009 17:21:38 +0800 Subject: [PATCH] ENH: add AlosPalsarModel (WIP) --- .../ossim/ossimAlosPalsarModel.cpp | 672 ++++++++++++++++++ .../ossim/ossimAlosPalsarModel.h | 129 ++++ 2 files changed, 801 insertions(+) create mode 100644 Utilities/otbossimplugins/ossim/ossimAlosPalsarModel.cpp create mode 100644 Utilities/otbossimplugins/ossim/ossimAlosPalsarModel.h diff --git a/Utilities/otbossimplugins/ossim/ossimAlosPalsarModel.cpp b/Utilities/otbossimplugins/ossim/ossimAlosPalsarModel.cpp new file mode 100644 index 0000000000..f2a7f95309 --- /dev/null +++ b/Utilities/otbossimplugins/ossim/ossimAlosPalsarModel.cpp @@ -0,0 +1,672 @@ +//---------------------------------------------------------------------------- +// +// "Copyright Centre National d'Etudes Spatiales" +// "Copyright Centre for Remote Imaging, Sensing and Processing" +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +//---------------------------------------------------------------------------- +// $Id$ + +#include <ossimAlosPalsarModel.h> +#include <otb/GalileanEphemeris.h> +#include <otb/GeographicEphemeris.h> + +#include <otb/JSDDateTime.h> +#include <otb/GMSTDateTime.h> +#include <otb/CivilDateTime.h> + +#include <ossim/base/ossimTrace.h> +#include <otb/RefPoint.h> +#include <ers/AlosPalsar/AlosPalsarLeader/AlosPalsarLeader.h> +#include <otb/SensorParams.h> +#include <otb/PlatformPosition.h> +#include <ossim/base/ossimKeywordNames.h> + + +// Static trace for debugging +static ossimTrace traceDebug("ossimAlosPalsarModel:debug"); + +#include <string> +#include <algorithm> + +namespace ossimplugins +{ + + +RTTI_DEF1(ossimAlosPalsarModel, "ossimAlosPalsarModel", ossimGeometricSarSensorModel); + +ossimAlosPalsarModel::ossimAlosPalsarModel(): + theNumberSRGR(0), + thePixelSpacing(0), + theAlosPalsarleader(NULL) +{ + theSRGRCoeffset[0][0]=0.0; + theSRGRCoeffset[0][1]=0.0; + theSRGRCoeffset[0][2]=0.0; +} + +ossimAlosPalsarModel::~ossimAlosPalsarModel() +{ +} + +ossimString ossimAlosPalsarModel::getClassName() const +{ + return ossimString("ossimAlosPalsarModel"); +} + +ossimObject* ossimAlosPalsarModel::dup() const +{ + return new ossimAlosPalsarModel(*this); +} + +double ossimAlosPalsarModel::getSlantRangeFromGeoreferenced(double col) const +{ + const double c = 2.99792458e+8; + double tn = theSRGRCoeffset[0][0] + theSRGRCoeffset[0][1] * col + theSRGRCoeffset[0][2] * col*col ; + return tn * (c/2.0); +} + +bool ossimAlosPalsarModel::InitSensorParams(const ossimKeywordlist &kwl, const char *prefix) +{ + const char* wave_length_str = kwl.find(prefix,"wave_length"); + double wave_length = atof(wave_length_str); + const char* fr_str = kwl.find(prefix,"fr"); + double fr = atof(fr_str)*1e6; + const char* fa_str = kwl.find(prefix,"fa"); + double fa = atof(fa_str); + + ossimString time_dir_pix = kwl.find(prefix,"time_dir_pix"); + time_dir_pix.upcase(); + //std::transform(time_dir_pix.begin(), time_dir_pix.end(), time_dir_pix.begin(), toupper); + ossimString time_dir_lin = kwl.find(prefix,"time_dir_lin"); + time_dir_lin.upcase(); + //std::transform(time_dir_lin.begin(), time_dir_lin.end(), time_dir_lin.begin(), toupper); + + //ellipsoid parameters + const char* ellip_maj_str = kwl.find(prefix,"ellip_maj"); + double ellip_maj = atof(ellip_maj_str) * 1000.0; // km -> m + const char* ellip_min_str = kwl.find(prefix,"ellip_min"); + double ellip_min = atof(ellip_min_str) * 1000.0; // km -> m + + if(_sensor != NULL) + { + delete _sensor; + } + + _sensor = new SensorParams(); + + if(strcmp(time_dir_pix.c_str(), "INCREASE") == 0) + { + _sensor->set_col_direction(1); + } + else + { + _sensor->set_col_direction(-1); + } + + if(strcmp(time_dir_lin.c_str(), "INCREASE") == 0) + { + _sensor->set_lin_direction(1); + } + else + { + _sensor->set_lin_direction(-1); + } + + _sensor->set_sightDirection(SensorParams::Right) ; + + double nlooks_az = atof(kwl.find(prefix,"nlooks_az")); + _sensor->set_nAzimuthLook(nlooks_az); + double n_rnglok = atof(kwl.find(prefix,"n_rnglok")); + _sensor->set_nRangeLook(n_rnglok); + + _sensor->set_prf(fa); + _sensor->set_sf(fr); + _sensor->set_rwl(wave_length); + + _sensor->set_semiMajorAxis(ellip_maj) ; + _sensor->set_semiMinorAxis(ellip_min) ; + + return true; +} + +bool ossimAlosPalsarModel::open(const ossimFilename& file) +{ + static const char MODULE[] = "ossimAlosPalsarModel::open"; + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << MODULE << " entered...\n" + << "file: " << file << "\n"; + } + + bool result = false; + ossimFilename leaFilename = file; + + /* + * Creation of the class allowing to store Leader file metadata + */ + if(theAlosPalsarleader != NULL) + { + delete theAlosPalsarleader; + theAlosPalsarleader = NULL; + } + + theAlosPalsarleader = new AlosPalsarLeader(); + + if ( leaFilename.exists() ) + { + result = isErsLeader(leaFilename); + if (result == false) + { + leaFilename = findErsLeader(file); + } + result = isErsLeader(leaFilename); + + if (result == true) + { + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) << "is ERS leader file..." + << "Begin reading Leader file" << std::endl; + } + /* + * Leader file data reading + */ + std::ifstream leaderFile(leaFilename, ios::in|ios::binary); + leaderFile>>*theAlosPalsarleader; + leaderFile.close(); + + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << "End reading Leader file" << std::endl; + } + } // matches: if ( result=isErsLeader(file) == True ) + + } // matches: if ( file.exists() ) + + if (traceDebug()) + { + this->print(ossimNotify(ossimNotifyLevel_DEBUG)); + + ossimNotify(ossimNotifyLevel_DEBUG) + << MODULE << " exit status = " << (result?"true":"false\n") + << std::endl; + } + + return result; + +} + + +bool ossimAlosPalsarModel::saveState(ossimKeywordlist& kwl, + const char* prefix) const +{ + static const char MODULE[] = "ossimAlosPalsarModel::saveState"; + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG)<< MODULE << " entered...\n"; + } + + bool result; + + char name[64]; + + //kwl.add(prefix, ossimKeywordNames::TYPE_KW, "ossimAlosPalsarModel", true); + + if (theAlosPalsarleader == NULL) + { + std::cout << "Error: AlosPalsarleader is NULL" << std::endl; + return false; + } + + result = theAlosPalsarleader->saveState(kwl); + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << MODULE << " exit status = " << (result?"true":"false\n") + << std::endl; + } + + return result; +} + +bool ossimAlosPalsarModel::loadState (const ossimKeywordlist &kwl, const char *prefix) +{ + static const char MODULE[] = "ossimAlosPalsarModel::loadState"; + + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " entered...\n"; + } + + const char* lookup = 0; + ossimString s; + + // Check the type first. + lookup = kwl.find(prefix, ossimKeywordNames::TYPE_KW); + if (lookup) + { + s = lookup; + if (s != getClassName()) + { + return false; + } + } + + // Load the base class. +// bool result = ossimGeometricSarSensorModel::loadState(kwl, prefix); + bool result = false; + result = InitPlatformPosition(kwl, prefix); + if (!result) + { + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_WARN) + << MODULE + << "\nCan't init platform position \n"; + } + } + + if (result) + { + result = InitSensorParams(kwl, prefix); + if (!result) + { + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_WARN) + << MODULE + << "\nCan't init sensor parameters \n"; + } + } + } + + if (result) + { + result = InitRefPoint(kwl, prefix); + if (!result) + { + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_WARN) + << MODULE + << "\nCan't init ref point \n"; + } + } + } + + if (result) + { + result = InitSRGR(kwl, prefix); + if (!result) + { + if (traceDebug()) + { + ossimNotify(ossimNotifyLevel_WARN) + << MODULE + << "\nCan't init ref point \n"; + } + } + } + + return result; +} + +bool ossimAlosPalsarModel::InitPlatformPosition(const ossimKeywordlist &kwl, const char *prefix) +{ + // const double PI = 3.14159265358979323846 ; + CivilDateTime ref_civil_date; + /* + * Ephemerisis reference date retrieval + */ + const char* eph_year_str = kwl.find(prefix,"eph_year"); + int eph_year = atoi(eph_year_str); + const char* eph_month_str = kwl.find(prefix,"eph_month"); + int eph_month = atoi(eph_month_str); + const char* eph_day_str = kwl.find(prefix,"eph_day"); + int eph_day = atoi(eph_day_str); + const char* eph_sec_str = kwl.find(prefix,"eph_sec"); + double eph_sec = atof(eph_sec_str); + + ref_civil_date.set_year(eph_year); + ref_civil_date.set_month(eph_month); + ref_civil_date.set_day(eph_day); + ref_civil_date.set_second((int)eph_sec); + ref_civil_date.set_decimal( eph_sec-(double)((int)eph_sec)); + + JSDDateTime ref_jsd_date(ref_civil_date); + + /* + * Ephemerisis time interval retrieval + */ + const char* eph_int_str = kwl.find(prefix, "eph_int"); + double eph_int = atof(eph_int_str); + /* + * Ephemerisis number retrieval + */ + const char* neph_str = kwl.find(prefix,"neph"); + int neph = atoi(neph_str); + + Ephemeris** ephemeris = new Ephemeris*[neph]; + + /* + * Ephemerisis retrieval + */ + for (int i=0;i<neph;i++) + { + double pos[3]; + double vit[3]; + char name[64]; + + + sprintf(name,"eph%i_posX",i); + const char* px_str = kwl.find(prefix,name); + pos[0] = atof(px_str); + + sprintf(name,"eph%i_posY",i); + const char* py_str = kwl.find(prefix,name); + pos[1] = atof(py_str); + + sprintf(name,"eph%i_posZ",i); + const char* pz_str = kwl.find(prefix,name); + pos[2] = atof(pz_str); + + + sprintf(name,"eph%i_velX",i); + const char* vx_str = kwl.find(prefix,name); + vit[0] = atof(vx_str); + + sprintf(name,"eph%i_velY",i); + const char* vy_str = kwl.find(prefix,name); + vit[1] = atof(vy_str); + + sprintf(name,"eph%i_velZ",i); + const char* vz_str = kwl.find(prefix,name); + vit[2] = atof(vz_str); + + /* + * Ephemerisis date + */ + JSDDateTime date(ref_jsd_date); + date.set_second(date.get_second() + i * eph_int); + date.NormDate(); + + GeographicEphemeris* eph = new GeographicEphemeris(date, pos, vit); + + ephemeris[i] = eph; + } + + /* + * Antenna position interpolator creation + */ + if (_platformPosition != NULL) + { + delete _platformPosition; + } + _platformPosition = new PlatformPosition(ephemeris,neph); + + /* + * Free of memory used by the ephemerisis list + */ + for (int i=0;i<neph;i++) + { + delete ephemeris[i]; + } + delete[] ephemeris; + + return true; +} + +bool ossimAlosPalsarModel::InitRefPoint(const ossimKeywordlist &kwl, const char *prefix) +{ + const char* sc_lin_str = kwl.find(prefix,"sc_lin"); + double sc_lin = atof(sc_lin_str); + + const char* sc_pix_str = kwl.find(prefix,"sc_pix"); + double sc_pix = atof(sc_pix_str); + + const char* inp_sctim_str = kwl.find(prefix,"inp_sctim"); + + const char* rng_gate_str = kwl.find(prefix,"zero_dop_range_time_f_pixel"); + double rng_gate = atof(rng_gate_str); + + if(_refPoint == NULL) + { + _refPoint = new RefPoint(); + } + + _refPoint->set_pix_col(sc_pix); + _refPoint->set_pix_line(sc_lin); + + char year_str[5]; + for (int i=0;i<4;i++) + { + year_str[i] = inp_sctim_str[i]; + } + year_str[4] = '\0'; + + char month_str[3]; + for (int i=4;i<6;i++) + { + month_str[i-4] = inp_sctim_str[i]; + } + month_str[2] = '\0'; + + char day_str[3]; + for (int i=6;i<8;i++) + { + day_str[i-6] = inp_sctim_str[i]; + } + day_str[2] = '\0'; + + char hour_str[3]; + for (int i=8;i<10;i++) + { + hour_str[i-8] = inp_sctim_str[i]; + } + hour_str[2] = '\0'; + + char min_str[3]; + for (int i=10;i<12;i++) + { + min_str[i-10] = inp_sctim_str[i]; + } + min_str[2] = '\0'; + + char sec_str[3]; + for (int i=12;i<14;i++) + { + sec_str[i-12] = inp_sctim_str[i]; + } + sec_str[2] = '\0'; + + char mili_str[4]; + for (int i=14;i<17;i++) + { + mili_str[i-14] = inp_sctim_str[i]; + } + mili_str[3] = '\0'; + + int year = atoi(year_str); + int month = atoi(month_str); + int day = atoi(day_str); + int hour = atoi(hour_str); + int min = atoi(min_str); + int sec = atoi(sec_str); + double mili = atof(mili_str); + + + CivilDateTime date(year, month, day, hour * 3600 + min * 60 + sec, mili/1000.0); + + if(_platformPosition != NULL) + { + Ephemeris * ephemeris = _platformPosition->Interpolate((JSDDateTime)date); + if (ephemeris == NULL) return false ; + _refPoint->set_ephemeris(ephemeris); + + delete ephemeris; + } + else + { + return false; + } + + double c = 2.99792458e+8; + + double distance = (rng_gate*1e-3 + ((double)sc_pix)*_sensor->get_nRangeLook()/_sensor->get_sf()) * (c/2.0); + + _refPoint->set_distance(distance); + + // in order to use ossimSensorModel::lineSampleToWorld + const char* nbCol_str = kwl.find(prefix,"num_pix"); + const char* nbLin_str = kwl.find(prefix,"num_lines"); + theImageSize.x = atoi(nbCol_str); + theImageSize.y = atoi(nbLin_str); + theImageClipRect = ossimDrect(0, 0, theImageSize.x-1, theImageSize.y-1); + + // Ground Control Points extracted from the model : corner points + std::list<ossimGpt> groundGcpCoordinates ; + std::list<ossimDpt> imageGcpCoordinates ; + // first line first pix + const char* lon_str = kwl.find("first_line_first_pixel_lon"); + double lon = atof(lon_str); + const char* lat_str = kwl.find("first_line_first_pixel_lat"); + double lat = atof(lat_str); + if (lon > 180.0) lon -= 360.0; + ossimDpt imageGCP1(0,0); + ossimGpt groundGCP1(lat, lon, 0.0); + groundGcpCoordinates.push_back(groundGCP1) ; + imageGcpCoordinates.push_back(imageGCP1) ; + // first line last pix + lon_str = kwl.find("first_line_last_pixel_lon"); + lon = atof(lon_str); + lat_str = kwl.find("first_line_last_pixel_lat"); + lat = atof(lat_str); + if (lon > 180.0) lon -= 360.0; + ossimDpt imageGCP2(theImageSize.x-1, 0); + ossimGpt groundGCP2(lat, lon, 0.0); + groundGcpCoordinates.push_back(groundGCP2) ; + imageGcpCoordinates.push_back(imageGCP2) ; + // last line last pix + lon_str = kwl.find("last_line_last_pixel_lon"); + lon = atof(lon_str); + lat_str = kwl.find("last_line_last_pixel_lat"); + lat = atof(lat_str); + if (lon > 180.0) lon -= 360.0; + ossimDpt imageGCP3(theImageSize.x-1,theImageSize.y-1); + ossimGpt groundGCP3(lat, lon, 0.0); + groundGcpCoordinates.push_back(groundGCP3) ; + imageGcpCoordinates.push_back(imageGCP3) ; + // last line first pix + lon_str = kwl.find("last_line_first_pixel_lon"); + lon = atof(lon_str); + lat_str = kwl.find("last_line_first_pixel_lat"); + lat = atof(lat_str); + if (lon > 180.0) lon -= 360.0; + ossimDpt imageGCP4(0,theImageSize.y-1); + ossimGpt groundGCP4(lat, lon, 0.0); + groundGcpCoordinates.push_back(groundGCP4) ; + imageGcpCoordinates.push_back(imageGCP4) ; + + // Default optimization + optimizeModel(groundGcpCoordinates, imageGcpCoordinates) ; + + return true; +} + +bool ossimAlosPalsarModel::InitSRGR(const ossimKeywordlist &kwl, const char *prefix) +{ + // Product type = PRI + ossimString filename(kwl.find("filename")); + filename.upcase(); + //std::transform(filename.begin(), filename.end(), filename.begin(), toupper); + string::size_type loc = filename.find("PRI"); + if( loc != string::npos ) { + _isProductGeoreferenced = true; + } else { + _isProductGeoreferenced = false; + } + + // Number of SRGR Coef + theNumberSRGR = 3; + + // Range time for first mid and last pixel + double t1 = atof(kwl.find("zero_dop_range_time_f_pixel"))*1e-3; + double t2 = atof(kwl.find("zero_dop_range_time_c_pixel"))*1e-3; + double t3 = atof(kwl.find("zero_dop_range_time_l_pixel"))*1e-3; + + // Range pixels numbers corresponding + // Todo : check if it works with "DECREASING LINE TIME" + // double x1 = 0.0; + double x2 = atof(kwl.find("sc_pix")) - 1.0; + double x3 = 2.0*(x2+1.0) -1.0 ; + + theSRGRCoeffset[0][0] = t1; + theSRGRCoeffset[0][1] = ((t2-t1)/(x2*x2)+(t1-t3)/(x3*x3))/((1.0/x2)-(1.0/x3)); + theSRGRCoeffset[0][2] = ((t2-t1)/x2 + (t1-t3)/x3)/(x2-x3); + + return true; +} + +bool ossimAlosPalsarModel::isErsLeader(const ossimFilename& file) const +{ + std::ifstream candidate(file, ios::in | ios::binary); + char ersFileName[16]; + + candidate.seekg(48); + if ( candidate.bad() or candidate.eof() ) + { + return false; + } + candidate.read(ersFileName, 16); + if ( candidate.bad() or candidate.eof() ) + { + return false; + } + candidate.close(); + + ossimString ersString(ersFileName); + + if ( ( ersString.find("ERS") == 0 ) && + ( ersString.find(".SAR.") == 4 ) && + ( ersString.find("LEAD") == 12 ) ) + { + return true; + } + else + { + return false; + } + +} + +ossimFilename ossimAlosPalsarModel::findErsLeader(const ossimFilename& file) const +{ + ossimFilename leaFile = file; + ossimString datString("DAT_01"); + ossimString nulString("NUL_DAT"); + ossimString vdfString("VDF_DAT"); + ossimString leaString("LEA_01"); + if ((file.fileNoExtension() == datString) + || (file.fileNoExtension() == nulString) + || (file.fileNoExtension() == leaString)) + { + leaFile.setFile(leaString); + if (leaFile.exists()) + { + return leaFile; + } + } + return file; +} + +} + diff --git a/Utilities/otbossimplugins/ossim/ossimAlosPalsarModel.h b/Utilities/otbossimplugins/ossim/ossimAlosPalsarModel.h new file mode 100644 index 0000000000..85d6245837 --- /dev/null +++ b/Utilities/otbossimplugins/ossim/ossimAlosPalsarModel.h @@ -0,0 +1,129 @@ +//---------------------------------------------------------------------------- +// +// "Copyright Centre National d'Etudes Spatiales" +// "Copyright Centre for Remote Imaging, Sensing and Processing" +// +// License: LGPL +// +// See LICENSE.txt file in the top level directory for more details. +// +//---------------------------------------------------------------------------- +// $Id$ + +#ifndef ossimAlosPalsarModel_H +#define ossimAlosPalsarModel_H + +#include <otb/JSDDateTime.h> +#include <ossimGeometricSarSensorModel.h> + +#include <ossim/projection/ossimMapProjection.h> +#include <ossim/base/ossimIpt.h> +#include <ossim/base/ossimFilename.h> +#include <ossim/base/ossimGpt.h> +#include <ossim/base/ossimDpt.h> + +#include <iostream> + +namespace ossimplugins +{ + +class PlatformPosition; +class SensorParams; +class RefPoint; +class AlosPalsarLeader; +/** + * @brief This class is able to direct localisation and indirect localisation using the AlosPalsar sensor model + * + */ +class ossimAlosPalsarModel : public ossimGeometricSarSensorModel +{ +public: + /** + * @brief Constructor + */ + ossimAlosPalsarModel(); + + /** + * @brief Destructor + */ + virtual ~ossimAlosPalsarModel(); + + /** + * @brief Method to return the class name. + * @return The name of this class. + */ + virtual ossimString getClassName() const; + + /** + * @brief Returns pointer to a new instance, copy of this. + */ + virtual ossimObject* dup() const; + + /** + * @brief This function associates an image column number to a slant range when the image is georeferenced (ground projected) + * @param col Column coordinate of the image point + */ + virtual double getSlantRangeFromGeoreferenced(double col) const; + + /** + * @brief Method to instantiate model from the leader file. + * @param file + * @return true on success, false on error. + */ + bool open(const ossimFilename& file); + + /** + * @brief Method to save object state to a keyword list. + * @param kwl Keyword list to save to. + * @param prefix added to keys when saved. + * @return true on success, false on error. + */ + virtual bool saveState(ossimKeywordlist& kwl, + const char* prefix=0) const; + + /** + * @brief Method to the load (recreate) the state of the object from a + * keyword list. Return true if ok or false on error. + * @return true if load OK, false on error + */ + virtual bool loadState (const ossimKeywordlist &kwl, const char *prefix=0); + +protected: + virtual bool InitPlatformPosition(const ossimKeywordlist &kwl, const char *prefix); + virtual bool InitSensorParams(const ossimKeywordlist &kwl, const char *prefix); + virtual bool InitRefPoint(const ossimKeywordlist &kwl, const char *prefix); + /** + * @brief Initializes the Slant Range for each Ground Range data sets : theNumberSRGR,theSRGRCoeffset,_srgr_update,thePixelSpacing,_isProductGeoreferenced + */ + virtual bool InitSRGR(const ossimKeywordlist &kwl, const char *prefix); + +private: + /** + * @brief Slant Range for each Ground Range (SRGR) number of coefficients sets + */ + int theNumberSRGR; + /** + * @brief SRGR coefficient sets + */ + double theSRGRCoeffset[1][3]; + /** + * @brief Pixel spacing + */ + double thePixelSpacing; + + /** + * @brief List of metadata contained in the Leader file + */ + AlosPalsarLeader *theAlosPalsarleader; + + + + virtual bool isErsLeader(const ossimFilename& file) const; + virtual ossimFilename findErsLeader(const ossimFilename& file) const; + + TYPE_DATA + +}; + +} +#endif -- GitLab