HelmertTransform.cpp

Go to the documentation of this file.
00001 #pragma ident "$Id: HelmertTransform.cpp 3140 2012-06-18 15:03:02Z susancummins $"
00002 
00003 //============================================================================
00004 //
00005 //  This file is part of GPSTk, the GPS Toolkit.
00006 //
00007 //  The GPSTk is free software; you can redistribute it and/or modify
00008 //  it under the terms of the GNU Lesser General Public License as published
00009 //  by the Free Software Foundation; either version 2.1 of the License, or
00010 //  any later version.
00011 //
00012 //  The GPSTk is distributed in the hope that it will be useful,
00013 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 //  GNU Lesser General Public License for more details.
00016 //
00017 //  You should have received a copy of the GNU Lesser General Public
00018 //  License along with GPSTk; if not, write to the Free Software Foundation,
00019 //  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
00020 //  
00021 //  Copyright 2009, The University of Texas at Austin
00022 //
00023 //============================================================================
00024 
00025 #include <iostream>
00026 
00027 #include "HelmertTransform.hpp"
00028 
00029 using namespace gpstk;
00030 using namespace std;
00031 
00032 // Exception messages
00033 
00034 static const string unknownExceptionTeXvt =
00035    "Unknown ReferenceFrame - Cannot perform Helmert Transformation.";
00036 static const string unknownDefinitionTeXvt =
00037    "Unknown ReferenceFrame - Cannot define an Unknown transform.";
00038 static const string backwardsDefinition =
00039    "Cannot define transformation backwards. A transformation is already"
00040    " defined in the reverse order.";
00041 
00042 // Units
00043 
00044 const double HelmertTransform::MAS = 7.71605e-10;
00045 const double HelmertTransform::PPB = 1e-9;
00046 
00047 // Used by the static instance method to build the maps the first time around.
00048 
00049 HelmertTransform::HelmertTransform()
00050    throw()
00051 {
00052    populateTransformMaps();
00053 }
00054 
00055 // Protected; shouldn't be used. Here to keep the compiler from defining it.
00056 
00057 HelmertTransform& HelmertTransform::operator=( const HelmertTransform& right )
00058    throw()
00059 {
00060    return *this;
00061 }
00062 
00063 // Funtion static variable, initialized the first time around only.
00064 
00065 HelmertTransform& HelmertTransform::instance()
00066 {
00067    static HelmertTransform inst;
00068    return inst;
00069 }
00070 
00072 
00073 void HelmertTransform::defineTransform(const HelmertTransform::TransformParameters& tp,
00074                                        const ReferenceFrame& to,
00075                                        const ReferenceFrame& from)
00076    throw(InvalidParameter)
00077 {
00078    // Sanity check; no Unknown frames allowed.
00079    if (from == ReferenceFrame::Unknown || to == ReferenceFrame::Unknown)
00080    {
00081       throw InvalidParameter(unknownDefinitionTeXvt);
00082    }
00083    
00084    // Start searching.
00085    LookupMap::iterator iter = fromMap.find(from);
00086    if (iter != fromMap.end())
00087    {
00088       iter->second[to] = buildTransform(tp);
00089       fromMap[from] = iter->second;
00090    }
00091    else  // Look for it in reverse order.
00092    {
00093       iter = fromMap.find(to);
00094       if (iter != fromMap.end())
00095       {
00096             // Check in reverse order.
00097          TransformMap::iterator transIter = (iter->second).find(from);
00098          if (transIter != (iter->second).end())
00099          {
00100             // Since it is defined in reverse already, throw an error
00101             // We don't allow reverse redefinitions right now because it
00102             // could cause some ambiguity in the maps.
00103             throw InvalidParameter(backwardsDefinition);
00104          }
00105       }
00106       // Since it didn't trip that trap, build it their way.
00107       TransformMap tmap;
00108       tmap[to] = buildTransform(tp);
00109       fromMap[from] = tmap;
00110    }
00111 }
00112 
00113 
00114 // Returns the from/to combination if both from/to and to/from are defined.
00115 // This method is VERY similar to the defineTransform method.
00116 
00117 HelmertTransform::Transform& HelmertTransform::getTransform(const ReferenceFrame& from,
00118                                                             const ReferenceFrame& to)
00119    throw(InvalidParameter)
00120 {
00121    LookupMap::iterator iter = fromMap.find(from);
00122    if (iter == fromMap.end())
00123    {
00124       throw InvalidParameter("No Transformations defined from " +
00125                               from.asString() + " to " +
00126                               to.asString() +
00127                               ". Could it be defined as " +
00128                               to.asString() + " to " + 
00129                               from.asString() + "?");
00130    }
00131    else
00132    {
00133          TransformMap::iterator transIter = (iter->second).find(to);
00134          if (transIter != iter->second.end())
00135          {
00136             return transIter->second;
00137          }
00138          else
00139          {
00140             throw InvalidParameter("No Transformations defined from " +
00141                                     from.asString() + " to " +
00142                                     to.asString() +
00143                                     ". Could it be defined as " +
00144                                     to.asString() + " to " + 
00145                                     from.asString() + "?");
00146          }
00147    }
00148 }
00149 
00151 
00152 // Position transform, calls the triple method posTransform.
00153 
00154 Position HelmertTransform::transform(const ReferenceFrame& to,
00155                                      const Position& pos      )
00156    throw(InvalidParameter)
00157 {
00158    // Throw an error if either Reference Frame is unknown.
00159    if (pos.getReferenceFrame() == ReferenceFrame::Unknown ||
00160          to == ReferenceFrame::Unknown)
00161       throw InvalidParameter(unknownExceptionTeXvt);
00162 
00163    Position cartPos = pos;
00164    cartPos.transformTo(Position::Cartesian);
00165    Triple newPosition = (Triple)cartPos;
00166    newPosition = posTransform(cartPos.getReferenceFrame(), to, newPosition);
00167 
00168    cartPos.setReferenceFrame(to);
00169    // Not sure if this needs to use setECEF or if it is already set.
00170    return cartPos.setECEF(newPosition[0], newPosition[1], newPosition[2]);
00171 }
00172 
00173 
00174 // Xvt transform, calls the triple methods posTransform and velTransform.
00175 
00176 Xvt HelmertTransform::transform(const ReferenceFrame& to,
00177                                 const Xvt& pos           )
00178    throw(InvalidParameter)
00179 {
00180    if (pos.frame == ReferenceFrame::Unknown || to == ReferenceFrame::Unknown)
00181       throw InvalidParameter(unknownExceptionTeXvt);
00182 
00183    Xvt newXvt = pos;
00184 
00185    newXvt.x = posTransform(newXvt.frame, to, newXvt.x);
00186    newXvt.v = velTransform(newXvt.frame, to, newXvt.v);
00187 
00188    newXvt.frame = to;
00189    return newXvt;
00190 }
00191 
00192 
00193 // Triple position transform, calls the Vector method posTransform.
00194 
00195 Triple HelmertTransform::posTransform(const ReferenceFrame& from,
00196                                       const ReferenceFrame& to,
00197                                       const Triple& pos          )
00198    throw(InvalidParameter)
00199 {
00200    if (from == ReferenceFrame::Unknown || to == ReferenceFrame::Unknown)
00201       throw InvalidParameter(unknownExceptionTeXvt);
00202    
00203    Vector<double> newPos(3,0.0);
00204    newPos(0) = pos[0];
00205    newPos(1) = pos[1];
00206    newPos(2) = pos[2];
00207    
00208    newPos = posTransform(from, to, newPos);
00209    
00210    return Triple(newPos(0), newPos(1), newPos(2));
00211 }
00212 
00213 
00214 // Triple velocity transform, calls the Vector method velTransform.
00215 
00216 Triple HelmertTransform::velTransform(const ReferenceFrame& from,
00217                                       const ReferenceFrame& to,
00218                                       const Triple& vel          )
00219    throw(InvalidParameter)
00220 {
00221    if (from == ReferenceFrame::Unknown || to == ReferenceFrame::Unknown)
00222       throw InvalidParameter(unknownExceptionTeXvt);
00223 
00224    Vector<double> newVel(3,0.0);
00225    newVel(0) = vel[0];
00226    newVel(1) = vel[1];
00227    newVel(2) = vel[2];
00228 
00229    newVel = velTransform(from, to, newVel);
00230 
00231    return Triple(newVel(0), newVel(1), newVel(2));
00232 }
00233 
00234 
00235 //Vector position transform, calls helperTransform with true as an arg
00236 
00237 Vector<double> HelmertTransform::posTransform(const ReferenceFrame& from,
00238                                               const ReferenceFrame& to,
00239                                               const Vector<double>& pos  )
00240    throw(InvalidParameter)
00241 {
00242    if (from == ReferenceFrame::Unknown || to == ReferenceFrame::Unknown)
00243       throw InvalidParameter(unknownExceptionTeXvt);
00244 
00245    return helperTransform(from, to, pos, true);
00246 }
00247 
00248 
00249 //Vector velocity transfrom, calls helperTransform with false as an arg.
00250 
00251 Vector<double> HelmertTransform::velTransform(const ReferenceFrame& from,
00252                                               const ReferenceFrame& to,
00253                                               const Vector<double>& vel  )
00254    throw(InvalidParameter)
00255 {
00256    if (from == ReferenceFrame::Unknown || to == ReferenceFrame::Unknown)
00257       throw InvalidParameter(unknownExceptionTeXvt);
00258 
00259    return helperTransform(from, to, vel, false);
00260 }
00261 
00263 
00264 // Looks up and resolves the needed transform, then applies it.
00265 // If translate is true, the translation vector is used, otherwise not.
00266 
00267 Vector<double> HelmertTransform::helperTransform(const ReferenceFrame& from,
00268                                                  const ReferenceFrame& to,
00269                                                  const Vector<double>& pvec,
00270                                                  bool translate             )
00271    throw(InvalidParameter)
00272 {
00273    Vector<double> vec = pvec;
00274 
00275    // Search for the from ReferenceFrame.  Forward definition lookup first.
00276    LookupMap::iterator iter = fromMap.find(from);
00277    if ( iter != fromMap.end())
00278    {
00279       // Find the "to" ReferenceFrame in the previous frames map.
00280       TransformMap::iterator transIter = (iter->second).find(to);
00281       if (transIter != (iter->second).end())
00282       {
00283          // Apply the transform, conditionally use the translation vector.
00284          vec = vec * (transIter->second).rotation;
00285          if (translate)
00286          {
00287             vec += (transIter->second).translation;
00288          }
00289          return vec;
00290       }
00291    }
00292    // Didn't return, so check it in reverse.
00293    iter = fromMap.find(to);
00294    if (iter == fromMap.end())
00295    {
00296            //Not defined either way, throw an exception
00297       throw InvalidParameter("Transform " + from.asString() + " to "
00298                               + to.asString() + " is not defined.");
00299    }
00300    // To is defined at the base level, search its map for From.
00301    // Searching for the reverse transformation.
00302    TransformMap::iterator transIter = (iter->second).find(from);
00303    if (transIter != (iter->second).end())
00304    {
00305       // Conditionally apply the translation, then apply the rotation.
00306       if (translate)
00307       {
00308          vec -= (transIter->second).translation;
00309       }
00310       vec = vec * (transIter->second).inverseRotation;
00311       return vec;
00312    }
00313    else
00314    {
00315       // Neither the to or from ReferenceFrame is defined at base level.
00316       throw InvalidParameter("Transform " + from.asString() + " to "
00317                              + to.asString() + " is not defined.");
00318    }
00319 } // end helperTransform();
00320 
00321 
00322 // Build the PZ90->WGS84 transform and register it.
00323 
00324 void HelmertTransform::populateTransformMaps()
00325 {
00326    HelmertTransform::TransformParameters pz;
00327       pz.scale = -3e-9;
00328       pz.r1 = -19 * MAS;
00329       pz.r2 = -4 * MAS;
00330       pz.r3 = 353 * MAS;
00331       pz.t1 =  0.0700;
00332       pz.t2 = -0.0567;
00333       pz.t3 = -0.7733;
00334       pz.description = "Parameters taken from ITRS, PZ-90 and WGS 84: current"
00335                        " realizations and the\nrelated transformation parameters "
00336                        "- C. Boucher, Z.Altamimi";
00337 
00338    ReferenceFrame rf(ReferenceFrame::WGS84);
00339    ReferenceFrame rf2(ReferenceFrame::PZ90);
00340    defineTransform(pz, rf, rf2);
00341 }
00342 
00343 
00344 // Builds a transform struct from a transform parameters struct.
00345 // This does not apply units to the parameters.
00346 
00347 HelmertTransform::Transform HelmertTransform::buildTransform(const HelmertTransform::TransformParameters& tp)
00348    throw()
00349 {
00350    HelmertTransform::Transform trans;
00351    trans.params = tp;
00352    trans.rotation = Matrix<double>(3,3,0.0);
00353 
00354    trans.rotation(0,0) = tp.scale + 1;
00355    trans.rotation(0,1) = -tp.r3;
00356    trans.rotation(0,2) = tp.r2;
00357 
00358    trans.rotation(1,0) = tp.r3;
00359    trans.rotation(1,1) = tp.scale + 1;
00360    trans.rotation(1,2) = -tp.r1;
00361 
00362    trans.rotation(2,0) = -tp.r2;
00363    trans.rotation(2,1) = tp.r1;
00364    trans.rotation(2,2) = tp.scale + 1;
00365 
00366    trans.translation = Vector<double>(3,0.0);
00367 
00368    trans.translation(0) = tp.t1;
00369    trans.translation(1) = tp.t2;
00370    trans.translation(2) = tp.t3;
00371 
00372    trans.inverseRotation = inverse(trans.rotation);
00373 
00374    return trans;
00375 }
00376 
00377 
00378 // Print out the contents of the Transform maps.
00379 
00380 void HelmertTransform::dump()
00381 {
00382    for (LookupMap::iterator out = fromMap.begin(); out != fromMap.end(); out)
00383    {
00384       cout << out->first << endl;
00385 
00386       TransformMap::iterator in; // Saves a little space in the For loop.
00387       for (in = (out->second).begin(); in != (out->second).end(); ++in)
00388       {
00389          cout << " -> " << (in->first) << endl;
00390       }
00391    }
00392 }

Generated on Fri May 24 03:31:07 2013 for GPS ToolKit Software Library by  doxygen 1.3.9.1