diff --git a/isis/src/base/apps/appjit/tsts/case1/from.lis b/isis/src/base/apps/appjit/tsts/case1/from.lis deleted file mode 100644 index 668e813906e7570197b0db516e492a51edce4cb3..0000000000000000000000000000000000000000 --- a/isis/src/base/apps/appjit/tsts/case1/from.lis +++ /dev/null @@ -1,2 +0,0 @@ -output/PSP_007556_2010_RED4.balance.cropped.cub -output/PSP_007556_2010_RED5.balance.cropped.cub diff --git a/isis/src/base/apps/appjit/tsts/case2/from.lis b/isis/src/base/apps/appjit/tsts/case2/from.lis deleted file mode 100644 index 668e813906e7570197b0db516e492a51edce4cb3..0000000000000000000000000000000000000000 --- a/isis/src/base/apps/appjit/tsts/case2/from.lis +++ /dev/null @@ -1,2 +0,0 @@ -output/PSP_007556_2010_RED4.balance.cropped.cub -output/PSP_007556_2010_RED5.balance.cropped.cub diff --git a/isis/src/base/apps/ascii2isis/tsts/bip/errors.txt b/isis/src/base/apps/ascii2isis/tsts/bip/errors.txt deleted file mode 100644 index e968340dcafd1d561101d8ea2991955a7b192eb5..0000000000000000000000000000000000000000 --- a/isis/src/base/apps/ascii2isis/tsts/bip/errors.txt +++ /dev/null @@ -1 +0,0 @@ -[2018-03-21 22:43:42] Failed ... No truth folder or files diff --git a/isis/src/base/apps/automos/tsts/bandbin/cubes.lis b/isis/src/base/apps/automos/tsts/bandbin/cubes.lis deleted file mode 100644 index 81e830029d89c4cb64e1af4c8f7c9fc7ae21d0f2..0000000000000000000000000000000000000000 --- a/isis/src/base/apps/automos/tsts/bandbin/cubes.lis +++ /dev/null @@ -1,2 +0,0 @@ -/usgs/cpkgs/isis3/testData/isis/src/base/apps/automos/tsts/bandbin/input/VIR_IR_1A_1_364768748_1.equi.crop.cub -/usgs/cpkgs/isis3/testData/isis/src/base/apps/automos/tsts/bandbin/input/VIR_IR_1A_1_364769700_1.equi.crop.cub diff --git a/isis/src/base/apps/automos/tsts/tolist/cubes.lis b/isis/src/base/apps/automos/tsts/tolist/cubes.lis deleted file mode 100644 index 3839a395cc395b3b68a337c132d819c39c3c4251..0000000000000000000000000000000000000000 --- a/isis/src/base/apps/automos/tsts/tolist/cubes.lis +++ /dev/null @@ -1,2 +0,0 @@ -/usgs/cpkgs/isis3/testData/isis/src/base/apps/automos/tsts/tolist/input/VIR_IR_1A_1_364768748_1.equi.crop.cub -/usgs/cpkgs/isis3/testData/isis/src/base/apps/automos/tsts/tolist/input/VIR_IR_1A_1_364769700_1.equi.crop.cub diff --git a/isis/src/base/apps/blend/tsts/themis/fromlist.lis b/isis/src/base/apps/blend/tsts/themis/fromlist.lis deleted file mode 100644 index 16efbd87dcb081180ff24ad154ed326e652fdedc..0000000000000000000000000000000000000000 --- a/isis/src/base/apps/blend/tsts/themis/fromlist.lis +++ /dev/null @@ -1,2 +0,0 @@ -/usgs/cpkgs/isis3/testData/isis/src/base/apps/blend/tsts/themis/input/I23851018.cub -/usgs/cpkgs/isis3/testData/isis/src/base/apps/blend/tsts/themis/input/I01086005.cub diff --git a/isis/src/base/apps/cam2map/tsts/targCodeFromNaifKeywordsObj/Makefile b/isis/src/base/apps/cam2map/tsts/targCodeFromNaifKeywordsObj/Makefile deleted file mode 100644 index 068d99b44ba1e240065544d1133817a762895a23..0000000000000000000000000000000000000000 --- a/isis/src/base/apps/cam2map/tsts/targCodeFromNaifKeywordsObj/Makefile +++ /dev/null @@ -1,17 +0,0 @@ -APPNAME = cam2map - -cam2mapTruth.cub.TOLERANCE = .000001 -cam2mapCheckRange.cub.TOLERANCE = .000001 - -include $(ISISROOT)/make/isismake.tsts - -commands: - $(APPNAME) from=$(INPUT)/test.cub \ - to=$(OUTPUT)/cam2mapTruth.cub \ - map=$(INPUT)/test.map \ - lonseam=continue \ - pixres=map \ - >& /dev/null; - catlab from=$(OUTPUT)/cam2mapTruth.cub \ - to=$(OUTPUT)/cubeLabel.pvl \ - >& /dev/null; diff --git a/isis/src/base/apps/equalizer/tsts/nonOverlapRetryBoth/Makefile b/isis/src/base/apps/equalizer/tsts/nonOverlapRetryBoth/Makefile index 4860d96539440fe2cf65e0a28c8fcb9b9b99666b..48ded0bc4ef09fb5ed766249ea4c30913ee2a108 100644 --- a/isis/src/base/apps/equalizer/tsts/nonOverlapRetryBoth/Makefile +++ b/isis/src/base/apps/equalizer/tsts/nonOverlapRetryBoth/Makefile @@ -1,12 +1,14 @@ # This tests calculating statistics for input with non-overlapping files, -# correcting the input list by REMOVING non-overlaps and recalculating to -# determine normalization gains and offsets for equalization, +# correcting the input list by REMOVING non-overlaps and recalculating to +# determine normalization gains and offsets for equalization, # and then applying corrections. # # NOTE: An exception occurs when there are non-overlaps during calculation, # it is handled and the output is sent to nonOverlapError.txt APPNAME = equalizer +I10047011EDR.proj.reduced.cub.TOLERANCE = .00001 + include $(ISISROOT)/make/isismake.tsts commands: diff --git a/isis/src/base/apps/isisminer/tsts/gisintersect/MercuryQuadGeoms.pvl b/isis/src/base/apps/isisminer/tsts/gisintersect/MercuryQuadGeoms.pvl deleted file mode 100644 index dbc7674466fe148364c45e1a9f981855592e4d15..0000000000000000000000000000000000000000 --- a/isis/src/base/apps/isisminer/tsts/gisintersect/MercuryQuadGeoms.pvl +++ /dev/null @@ -1,8 +0,0 @@ -Object = MercuryQuadGeoms - - Object = H1-Borealis - Keyword = "Value" - EndObject - -EndObject -End diff --git a/isis/src/base/apps/isisminer/tsts/resourceManager/isisTruth.pvl b/isis/src/base/apps/isisminer/tsts/resourceManager/isisTruth.pvl deleted file mode 100644 index 7a67a32a797c809e796ba1a03e369184b87b3c50..0000000000000000000000000000000000000000 --- a/isis/src/base/apps/isisminer/tsts/resourceManager/isisTruth.pvl +++ /dev/null @@ -1,18 +0,0 @@ -Object = IsisCube - SpacecraftName = "MARS GLOBAL SURVEYOR" - InstrumentId = MOC-WA - TargetName = Mars - StartTime = 1997-10-20T10:58:37.46 - StopTime = 1997-10-20T11:03:44.66 - CrosstrackSumming = 4 - DowntrackSumming = 4 - FocalPlaneTemperature = 213.1 - GainModeId = 1A - LineExposureDuration = 100.000000 - MissionPhaseName = AB-1 - OffsetModeId = 5 - SpacecraftClockCount = 561812335:32 - RationaleDesc = "OLYMPUS MONS SPECIAL RED WIDE ANGLE" - FirstLineSample = 673 -End_Object -End diff --git a/isis/src/base/apps/isisminer/tsts/resourceManager/pvls.lis b/isis/src/base/apps/isisminer/tsts/resourceManager/pvls.lis deleted file mode 100644 index 593b9347bb90cf631da058310b5c381b369229d2..0000000000000000000000000000000000000000 --- a/isis/src/base/apps/isisminer/tsts/resourceManager/pvls.lis +++ /dev/null @@ -1,5 +0,0 @@ -isisTruth.pvl -isisTruth.pvl - - - diff --git a/isis/src/base/objs/Spice/Spice.cpp b/isis/src/base/objs/Spice/Spice.cpp index 8b4ae4887e2cec558f4ca0449496c286ac8fec50..f902508f301dc6e69a2e278a5c9a593cf4a7f9c8 100644 --- a/isis/src/base/objs/Spice/Spice.cpp +++ b/isis/src/base/objs/Spice/Spice.cpp @@ -258,7 +258,12 @@ namespace Isis { *m_ckCode = *m_ikCode; if (!m_target->isSky()) { + // Get target body code and radii and store them in the Naif group + // DAC modified to look for and store body code so that the radii keyword name + // will be able to be constructed even for new bodies not in the standard PCK yet. QString radiiKey = "BODY" + Isis::toString(m_target->naifBodyCode()) + "_RADII"; + QVariant result = m_target->naifBodyCode(); + storeValue("BODY_CODE", 0, SpiceIntType, result); std::vector radii(3,Distance()); radii[0] = Distance(getDouble(radiiKey, 0), Distance::Kilometers); radii[1] = Distance(getDouble(radiiKey, 1), Distance::Kilometers); diff --git a/isis/src/base/objs/Spice/Spice.h b/isis/src/base/objs/Spice/Spice.h index ab0631b7e271dc63cda537667f3a714ccf7256cf..6e326ccc553c5ac5f676441ef46366d37c97c1fe 100644 --- a/isis/src/base/objs/Spice/Spice.h +++ b/isis/src/base/objs/Spice/Spice.h @@ -269,7 +269,7 @@ namespace Isis { * @history 2015-07-21 Kristin Berry - Added additional NaifStatus::CheckErrors() to see if any * NAIF errors were signaled. References #2248. * @history 2016-05-18 Jeannie Backer and Stuart Sides - Moved the construction of the Target - * after the NAIF kenels have been loaded or the NAIF keywords + * after the NAIF kernels have been loaded or the NAIF keywords * have been pulled from the cube labels, so we can find target * body codes that are defined in kernels and not just body codes * build into spicelib. References #3934 @@ -278,6 +278,13 @@ namespace Isis { * m_et is set. References #4476. * @history 2016-10-21 Jeannie Backer - Reorder method signatures and member variable * declarations to fit ISIS coding standards. References #4476. + * @history 2018-06-07 Debbie A Cook - Added BODY_CODE to Naif keywords. This code + * is used in the target body radii keyword name. Isis retrieves this code + * from the standard PCK. Because target bodies new to Naif are not + * included in the standard PCK, missions create a special body-specific + * PCK to define the new body, including its body code. This PCK is only + * loaded in spiceinit so the code needs to be saved so that the radii + * keyword can be created to retrieve the target radii. */ class Spice { public: diff --git a/isis/src/base/objs/Spice/Spice.truth b/isis/src/base/objs/Spice/Spice.truth index 98bb6a3b8e07cffb7113fb19be5c940fd8af9b11..a4d8a770ac925057026601f46d571f6e2749b17e 100644 --- a/isis/src/base/objs/Spice/Spice.truth +++ b/isis/src/base/objs/Spice/Spice.truth @@ -2,7 +2,7 @@ Unit test for Isis::Spice Testing unknown target ... **ERROR** Unable to look up NAIF body code for this Target. **I/O ERROR** Could not convert Target [Mard] to NAIF body code. -**I/O ERROR** Can not find [BODY_FRAME_CODE] in text kernels. +**I/O ERROR** Can not find [BODY_CODE] in text kernels. Creating Spice object ... BodyCode = 499 @@ -592,6 +592,7 @@ Target Name = Mars Get Stored Naif Keywords... Object = NaifKeywords + BODY_CODE = 499 BODY499_RADII = (3397.0, 3397.0, 3375.0) BODY_FRAME_CODE = 10014 FRAME_MGS_MOC = -94031 diff --git a/isis/src/base/objs/SurfacePoint/SurfacePoint.cpp b/isis/src/base/objs/SurfacePoint/SurfacePoint.cpp index 09a30dad785940cc2a69172bb9f46f99eed71282..9e0656784591ddf6d94ff300556872ba79fc5dc2 100644 --- a/isis/src/base/objs/SurfacePoint/SurfacePoint.cpp +++ b/isis/src/base/objs/SurfacePoint/SurfacePoint.cpp @@ -6,6 +6,7 @@ #include "IString.h" #include "Latitude.h" #include "Longitude.h" +#include "SpecialPixel.h" using namespace boost::numeric::ublas; using namespace std; @@ -308,13 +309,37 @@ namespace Isis { } + /** + * Set surface point in rectangular coordinates + * + * @param x x value of body-fixed coordinate of surface point + * @param y y value of body-fixed coordinate of surface point + * @param z z value of body-fixed coordinate of surface point + * + * @return void + */ + void SurfacePoint::SetRectangularCoordinates(const Displacement &x, + const Displacement &y, + const Displacement &z) { + // Wipe out current local radius to ensure it will be recalculated in SetRectangularPoint + p_localRadius = Distance(); + + SetRectangularPoint(x, y, z); + } + + /** * Set the rectangular sigmas into the rectangular variance/covariance - * matrix. + * matrix with diagonal element units of km^2, km^2, and km^2.. * * @param xSigma x sigma of body-fixed coordinate of surface point * @param ySigma y sigma of body-fixed coordinate of surface point * @param zSigma z sigma of body-fixed coordinate of surface point + * + * @internal + * @history 2017-07-25 Debbie A. Cook Added documentation and corrected units for diagonal + * elements to be km^2 instead of m^2. + * @history 2017-11-22 Debbie A. Cook Updated call to SetRectangularMatrix */ void SurfacePoint::SetRectangularSigmas(const Distance &xSigma, const Distance &ySigma, @@ -330,19 +355,21 @@ namespace Isis { covar(0,0) = xSigma.meters() * xSigma.meters(); covar(1,1) = ySigma.meters() * ySigma.meters(); covar(2,2) = zSigma.meters() * zSigma.meters(); - SetRectangularMatrix(covar); + SetRectangularMatrix(covar, Meters); } /** - * Set rectangular covariance matrix + * Set rectangular covariance matrix and store in units of km**2 * - * @param covar Rectangular variance/covariance matrix (units are m**2) + * @param covar Rectangular variance/covariance matrix + * @param units Units of matrix are units**2 * * @return void */ - void SurfacePoint::SetRectangularMatrix( - const symmetric_matrix &covar) { + void SurfacePoint::SetRectangularMatrix(const symmetric_matrix &covar, + SurfacePoint::CoordUnits units) { + // Make sure the point is set first if (!Valid()) { IString msg = "A point must be set before a variance/covariance matrix " @@ -350,22 +377,39 @@ namespace Isis { throw IException(IException::Programmer, msg, _FILEINFO_); } - if(p_rectCovar) { + // Make sure the units are valid + if (units != Kilometers && units != Meters) { + IString msg = "Units must be Kilometers or Meters"; + throw IException(IException::Programmer, msg, _FILEINFO_); + } + + // covar units are km**2 + if (p_rectCovar) { *p_rectCovar = covar; } else { p_rectCovar = new symmetric_matrix(covar); } + if (units == Meters) { + // Convert input matrix to km to hold in memory + (*p_rectCovar)(0,0) = covar(0,0)/1.0e6; + (*p_rectCovar)(0,1) = covar(0,1)/1.0e6; + (*p_rectCovar)(0,2) = covar(0,2)/1.0e6; + (*p_rectCovar)(1,1) = covar(1,1)/1.0e6; + (*p_rectCovar)(1,2) = covar(1,2)/1.0e6; + (*p_rectCovar)(2,2) = covar(2,2)/1.0e6; + } + SpiceDouble rectMat[3][3]; - // Compute the local radius of the surface point + // Compute the local radius of the surface point in meters. We will convert to km before saving the matrix. double x2 = p_x->meters() * p_x->meters(); double y2 = p_y->meters() * p_y->meters(); double z = p_z->meters(); double radius = sqrt(x2 + y2 + z*z); - // Should we use a matrix utility? + // *** TODO *** Replace this section with LinearAlgebra multiply calls and avoid having to create a Spice matrix rectMat[0][0] = covar(0,0); rectMat[0][1] = rectMat[1][0] = covar(0,1); rectMat[0][2] = rectMat[2][0] = covar(0,2); @@ -373,7 +417,7 @@ namespace Isis { rectMat[1][2] = rectMat[2][1] = covar(1,2); rectMat[2][2] = covar(2,2); - // Compute the Jacobian + // Compute the Jacobian in meters. Don't deal with unit mismatch yet to preserve precision. SpiceDouble J[3][3]; double zOverR = p_z->meters() / radius; double r2 = radius*radius; @@ -384,7 +428,7 @@ namespace Isis { J[1][0] = -p_y->meters() / (x2 + y2); J[1][1] = p_x->meters() / (x2 + y2); J[1][2] = 0.0; - J[2][0] = p_x->meters() / radius; + J[2][0] = p_x->meters() / radius; // This row is unitless J[2][1] = p_y->meters() / radius; J[2][2] = p_z->meters() / radius; @@ -394,12 +438,25 @@ namespace Isis { SpiceDouble mat[3][3]; mxm_c (J, rectMat, mat); mxmt_c (mat, J, mat); - (*p_sphereCovar)(0,0) = mat[0][0]; - (*p_sphereCovar)(0,1) = mat[0][1]; - (*p_sphereCovar)(0,2) = mat[0][2]; - (*p_sphereCovar)(1,1) = mat[1][1]; - (*p_sphereCovar)(1,2) = mat[1][2]; - (*p_sphereCovar)(2,2) = mat[2][2]; + if (units == Kilometers) { + // Now take care of unit mismatch between rect matrix in km and Jacobian in m + (*p_sphereCovar)(0,0) = mat[0][0] * 1.0e6; + (*p_sphereCovar)(0,1) = mat[0][1] * 1.0e6; + (*p_sphereCovar)(0,2) = mat[0][2] * 1000.0; + (*p_sphereCovar)(1,1) = mat[1][1] * 1.0e6; + + (*p_sphereCovar)(1,2) = mat[1][2] * 1000.0; + (*p_sphereCovar)(2,2) = mat[2][2]; + } + else { // (units == Meters) + // Convert matrix lengths from m to km + (*p_sphereCovar)(0,0) = mat[0][0]; + (*p_sphereCovar)(0,1) = mat[0][1]; + (*p_sphereCovar)(0,2) = mat[0][2] / 1000.0; + (*p_sphereCovar)(1,1) = mat[1][1]; + (*p_sphereCovar)(1,2) = mat[1][2] / 1000.0; + (*p_sphereCovar)(2,2) = mat[2][2] / 1.0e6; + } } @@ -430,7 +487,7 @@ namespace Isis { SpiceDouble rect[3]; latrec_c ( dradius, dlon, dlat, rect); - // Set local radius now since we have it to avoid calculating it later + // Set local radius now since we have it and avoid calculating it later p_localRadius = radius; SetRectangularPoint(Displacement(rect[0], Displacement::Kilometers), @@ -494,11 +551,18 @@ namespace Isis { /** - * Set the spherical sigmas into the spherical variance/covariance matrix. + * Set the spherical sigmas into the spherical variance/covariance matrix in diagonal units of + * radians^2, radians^2, km^2. * * @param latSigma Latitude sigma of body-fixed coordinate of surface point * @param lonSigma Longitude sigma of body-fixed coordinate of surface point * @param radiusSigma Radius sigma of body-fixed coordinate of surface point + * + * @internal + * @history 2017-07-25 Debbie A. Cook Added documentation and corrected units for covar(2,2) + * to be km^2 instead of m^2. + * @history 2017-11-22 Debbie A. Cook Set units for covar(2,2) back to m^2 which is not the default + * for the set method. */ void SurfacePoint::SetSphericalSigmas(const Angle &latSigma, const Angle &lonSigma, @@ -515,6 +579,7 @@ namespace Isis { sphericalCoordinate = (double) radiusSigma.meters(); covar(2,2) = sphericalCoordinate*sphericalCoordinate; + // Use default set units for radius of meters*meters SetSphericalMatrix(covar); } else { @@ -528,13 +593,13 @@ namespace Isis { /** - * Set the spherical sigmas (in meters) into the spherical variance/covariance + * Set the spherical sigmas (in Distance units) into the spherical variance/covariance * matrix. * * @param latSigma Latitude sigma of body-fixed coordinate of surface point - * in meters + * as a Distance * @param lonSigma Longitude sigma of body-fixed coordinate of surface point - * in meters + * as a Distance * @param radiusSigma Radius sigma of body-fixed coordinate of surface point * in meters * @internal @@ -551,23 +616,8 @@ namespace Isis { throw IException(IException::Programmer, msg, _FILEINFO_); } - // Convert Latitude sigma to radians - double latSigRadians = latSigma / GetLocalRadius(); - - // Convert Longitude sigma to radians - double convFactor = cos((double)GetLatitude().radians()); - double lonSigRadians; - - if (convFactor > 0.0000000000000001) { - lonSigRadians = lonSigma / (convFactor*GetLocalRadius()); - } - else { - // Brent Archinal suggested setting sigma to pi in the case of a point near the pole - lonSigRadians = PI; - } - - SetSphericalSigmas( Angle(latSigRadians, Angle::Radians), - Angle(lonSigRadians, Angle::Radians), radiusSigma); + SetSphericalSigmas(Angle(MetersToLatitude(latSigma.meters()),Angle::Radians), + Angle(MetersToLongitude(lonSigma.meters()), Angle::Radians), radiusSigma); } @@ -579,7 +629,8 @@ namespace Isis { * @return void */ void SurfacePoint::SetSphericalMatrix( - const symmetric_matrix & covar) { + const symmetric_matrix & covar, + SurfacePoint::CoordUnits units) { // Make sure the point is set first if (!Valid()) { @@ -588,13 +639,35 @@ namespace Isis { throw IException(IException::Programmer, msg, _FILEINFO_); } - if(p_sphereCovar) { - *p_sphereCovar = covar; + // Make sure the units are valid + if (units != Kilometers && units != Meters) { + IString msg = "Units must be Kilometers or Meters"; + throw IException(IException::Programmer, msg, _FILEINFO_); + } + + // Get the radius of the point in the same units as the input matrix when saving the input matrix + double radius = (double) GetLocalRadius().kilometers(); + + // Save the spherical matrix in km and km**2 + if (p_sphereCovar) { + *p_sphereCovar = covar; } else { p_sphereCovar = new symmetric_matrix(covar); } + + if (units == Meters) { + // Convert input matrix to km to store + (*p_sphereCovar)(0,0) = covar(0,0); + (*p_sphereCovar)(0,1) = covar(0,1); + (*p_sphereCovar)(0,2) = covar(0,2) / 1000.; + (*p_sphereCovar)(1,1) = covar(1,1); + (*p_sphereCovar)(1,2) = covar(1,2) / 1000.; + (*p_sphereCovar)(2,2) = covar(2,2) / 1.0e6; + radius = (double) GetLocalRadius().meters(); + } + // ***TODO*** Consider using LinearAlgebra matrix multiply and avoid creating SpiceDouble matrix. SpiceDouble sphereMat[3][3]; sphereMat[0][0] = covar(0,0); @@ -611,9 +684,8 @@ namespace Isis { // Get the lat/lon/radius of the point double lat = (double) GetLatitude().radians(); double lon = (double) GetLongitude().radians(); - double radius = (double) GetLocalRadius().meters(); - // Compute the Jacobian + // Compute the Jacobian in same units as input matrix. SpiceDouble J[3][3]; double cosPhi = cos(lat); double sinPhi = sin(lat); @@ -637,20 +709,149 @@ namespace Isis { SpiceDouble mat[3][3]; mxm_c (J, sphereMat, mat); mxmt_c (mat, J, mat); - // TODO Test to see if only the upper triangular portion of the matrix needs to be set - (*p_rectCovar)(0,0) = mat[0][0]; - (*p_rectCovar)(0,1) = mat[0][1]; - (*p_rectCovar)(0,2) = mat[0][2]; - (*p_rectCovar)(1,1) = mat[1][1]; - (*p_rectCovar)(1,2) = mat[1][2]; - (*p_rectCovar)(2,2) = mat[2][2]; + if (units == Kilometers) { + (*p_rectCovar)(0,0) = mat[0][0]; + (*p_rectCovar)(0,1) = mat[0][1]; + (*p_rectCovar)(0,2) = mat[0][2]; + (*p_rectCovar)(1,1) = mat[1][1]; + (*p_rectCovar)(1,2) = mat[1][2]; + (*p_rectCovar)(2,2) = mat[2][2]; + } + else { // (units == Meters) + // Convert to km + (*p_rectCovar)(0,0) = mat[0][0]/1.0e6; + (*p_rectCovar)(0,1) = mat[0][1]/1.0e6; + (*p_rectCovar)(0,2) = mat[0][2]/1.0e6; + (*p_rectCovar)(1,1) = mat[1][1]/1.0e6; + (*p_rectCovar)(1,2) = mat[1][2]/1.0e6; + (*p_rectCovar)(2,2) = mat[2][2]/1.0e6; + } // std::cout<<"Rcovar = "<& covar) { + + switch (type) { + case Latitudinal: + SetSphericalMatrix(covar, SurfacePoint::Kilometers); + break; + case Rectangular: + SetRectangularMatrix(covar, SurfacePoint::Kilometers); + break; + default: + IString msg ="Unknown surface point coordinate type enum [" + toString(type) + "]." ; + throw IException(IException::Programmer, msg, _FILEINFO_); + } + } + + /** + * Compute partial derivative of the conversion of the body-fixed surface point coordinate to the + * specified coordinate type. + * + * @param covar variance/covariance matrix + * + * @return void + */ + std::vector SurfacePoint::Partial(CoordinateType type, CoordIndex index) { + std::vector derivative(3); + switch (type) { + case Latitudinal: + derivative = LatitudinalDerivative(index); + break; + case Rectangular: + derivative = RectangularDerivative(index); + break; + default: + IString msg ="Unknown surface point coordinate type enum [" + toString(type) + "]." ; + throw IException(IException::Programmer, msg, _FILEINFO_); + } + return derivative; + } + + + /** + * Compute partial derivative of the conversion of the latitudinal coordinates to body-fixed + * rectangular coordinates with respect to the indicated coordinate. + * + * @param index Coordinate index + * + * @return @b std::vector The derivative of the latitudinal to body-fixed vector + */ + std::vector SurfacePoint::LatitudinalDerivative(CoordIndex index) { + std::vector derivative(3); + double rlat = GetLatitude().radians(); + double rlon = GetLongitude().radians(); + double sinLon = sin(rlon); + double cosLon = cos(rlon); + double sinLat = sin(rlat); + double cosLat = cos(rlat); + double radkm = GetLocalRadius().kilometers(); + + switch (index) { + case One: + derivative[0] = -radkm * sinLat * cosLon; + derivative[1] = -radkm * sinLon * sinLat; + derivative[2] = radkm * cosLat; + break; + case Two: + derivative[0] = -radkm * cosLat * sinLon; + derivative[1] = radkm * cosLat * cosLon; + derivative[2] = 0.0; + break; + case Three: + derivative[0] = cosLon * cosLat; + derivative[1] = sinLon * cosLat; + derivative[2] = sinLat; + break; + default: + IString msg = "Invalid coordinate index (must be less than 3)."; + throw IException(IException::Programmer, msg, _FILEINFO_); + } + return derivative; + } + + /** + * Compute partial derivative of the body-fixed rectangular coordinates with respect to the + * indicated coordinate. + * + * @param index Coordinate index + * + * @return @b std::vector The derivative of the body-fixed vector + */ + std::vector SurfacePoint::RectangularDerivative(CoordIndex index) { + std::vector derivative(3,0.0); + + switch (index) { + case One: + derivative[0] = 1.; + break; + case Two: + derivative[1] = 1.; + break; + case Three: + derivative[2] = 1.; + break; + default: + IString msg = "Invalid coordinate index (must be less than 3)."; + throw IException(IException::Programmer, msg, _FILEINFO_); + } + return derivative; + } + + /** * A naif array is a c-style array of size 3. The element types are double... * keep in mind a SpiceDouble is a double. The values' units are @@ -744,6 +945,483 @@ namespace Isis { } + /** + * This method returns a coordinate of a SurfacePoint + * + * @param type The coordinate type to return (see CoordinateType in .h file) + * @param index The coordinate index to return (1 <= index <= 3) + * @param units The units in which to return the coordinate value (see CoordinateUnits in .h file) + * + */ + double SurfacePoint::GetCoord(CoordinateType type, CoordIndex index, CoordUnits units) { + // TODO *** Is there a better way to satisfy the compiler that a value will be initialized? + // Don't the enums take care of preventing any other possibilities? no + double value = 0.; + + switch (type) { + + case Latitudinal: + + switch (index) { + + case One: // Latitude + value = LatToDouble(GetLatitude(), units); + break; + + case Two: // Longitude + value = LonToDouble(GetLongitude(), units); + break; + + case Three: // LocalRadius + value = DistanceToDouble(GetLocalRadius(), units); + break; + + default: + IString msg = "Invalid coordinate index (must be less than 3)."; + throw IException(IException::Programmer, msg, _FILEINFO_); + } + break; + + case Rectangular: + + switch (index) { + + case One: // X + value = DisplacementToDouble(GetX(), units); + break; + + case Two: // Y + value = DisplacementToDouble(GetY(), units); + break; + + case Three: // Z + value = DisplacementToDouble(GetZ(), units); + break; + + default: + IString msg = "Invalid coordinate index enum (must be less than 3)."; + throw IException(IException::Programmer, msg, _FILEINFO_); + } + break; + + default: + IString msg ="Unknown surface point coordinate type enum [" + toString(type) + "]." ; + throw IException(IException::Programmer, msg, _FILEINFO_); + } + return value; + } + + + /** + * This method returns a sigma of a SurfacePoint coordinate + * + * @param type The coordinate type to return (see CoordinateType in .h file) + * @param index The coordinate index to return (1 <= index <= 3) + * @param units The units in which to return the coordinate value (see CoordinateUnits in .h file) + * + */ + double SurfacePoint::GetSigma(CoordinateType type, CoordIndex index, CoordUnits units) { + double value = 0; // See first TODO in GetCoord + + switch (type) { + + case Latitudinal: + + switch (index) { + + case One: + value = DistanceToDouble(GetLatSigmaDistance(), units); + break; + + case Two: + value = DistanceToDouble(GetLonSigmaDistance(), units); + break; + + case Three: + value = DistanceToDouble(GetLocalRadiusSigma(), units); + break; + + default: + IString msg = "Invalid coordinate index (must be less than 3)."; + throw IException(IException::Programmer, msg, _FILEINFO_); + } + break; + + case Rectangular: + + switch (index) { + + case One: + value = DistanceToDouble(GetXSigma(), units); + break; + + case Two: + value = DistanceToDouble(GetYSigma(), units); + break; + + case Three: + value = DistanceToDouble(GetZSigma(), units); + break; + + default: + IString msg = "Invalid coordinate index (must be less than 3)."; + throw IException(IException::Programmer, msg, _FILEINFO_); + } + break; + + default: + IString msg ="Unknown surface point coordinate type enum [" + toString(type) + "]." ; + throw IException(IException::Programmer, msg, _FILEINFO_); + } + + return value; + } + + + /** + * This method returns a sigma of a SurfacePoint coordinate as a Distance + * + * @param type The coordinate type to return (see CoordinateType in .h file) + * @param index The coordinate index to return (1 <= index <= 3) + * + */ + Distance SurfacePoint::GetSigmaDistance(CoordinateType type, + CoordIndex index) { + Distance dist = Distance(); // See first TODO in GetCoord + + switch (type) { + + case Latitudinal: + + switch (index) { + + case One: + dist = GetLatSigmaDistance(); + break; + + case Two: + dist = GetLonSigmaDistance(); + break; + + case Three: + dist = GetLocalRadiusSigma(); + break; + + default: + IString msg = "Invalid coordinate index (must be less than 3)."; + throw IException(IException::Programmer, msg, _FILEINFO_); + } + break; + + case Rectangular: + + switch (index) { + + case One: + dist = GetXSigma(); + break; + + case Two: + dist = GetYSigma(); + break; + + case Three: + dist = GetZSigma(); + break; + + default: + IString msg = "Invalid coordinate index (must be less than 3)."; + throw IException(IException::Programmer, msg, _FILEINFO_); + } + break; + + default: + IString msg ="Unknown surface point coordinate type enum [" + toString(type) + "]." ; + throw IException(IException::Programmer, msg, _FILEINFO_); + } + + return dist; + } + + + /** + * This method returns a double version of a Displacement in the specified units + * + * @param disp The displacement to convert to a double + * @param units The units in which to return the displacement (see CoordinateUnits in .h file) + * + */ + double SurfacePoint::DisplacementToDouble(Displacement disp, CoordUnits units) { + double value; + + switch (units) { + + case Meters: + value = disp.meters(); + break; + + case Kilometers: + value = disp.kilometers(); + break; + + default: + IString msg = "Unrecognized unit for a Displacement (must be meters or kilometers)."; + throw IException(IException::Programmer, msg, _FILEINFO_); + } + return value; + } + + + /** + * This method returns a double version of a Distance in the specified units + * + * @param dist The distance to convert to a double + * @param units The units in which to return the distance (see CoordinateUnits in .h file) + * + */ + double SurfacePoint::DistanceToDouble(Distance dist, CoordUnits units) { + double value; + + switch (units) { + + case Meters: + value = dist.meters(); + break; + + case Kilometers: + value = dist.kilometers(); + break; + + default: + IString msg = "Unrecognized unit for a Distance (not meters or kilometers)."; + throw IException(IException::Programmer, msg, _FILEINFO_); + } + return value; + } + + + /** + * This method returns a double version of a Latitude in the specified units + * + * @param lat The latitude to convert to a double + * @param units The units in which to return the latitude (see CoordinateUnits in .h file) + * + */ + double SurfacePoint::LatToDouble(Latitude lat, CoordUnits units) { + double value; + + switch (units) { + + case Radians: + value = GetLatitude().radians(); + break; + + case Degrees: + value = GetLatitude().degrees(); + break; + + default: + IString msg = "Invalid unit for latitude (must be Radians or Degrees)."; + throw IException(IException::Programmer, msg, _FILEINFO_); + } + return value; + } + + + /** + * This method returns an angular measure of a distance in the direction + * of and relative to the latitude of the SurfacePoint. It should only be used to convert + * lengths relative to the SurfacePoint and in the direction of latitude. + * Typical usage would be to convert latitude sigmas and point + * corrections for the SurfacePoint. + * + * @param latLength The latitude in meters to convert to radian units + * @return @b LatDispAngle The converted linear measure in radian units + * + */ + double SurfacePoint::MetersToLatitude(double latLength) { + if (Valid() && !IsSpecial(latLength)) { + // Convert angle measure in meters to radians relative to latitude of SurfacePoint. + return latLength / GetLocalRadius().meters(); + } + else { + // Return Null to be consistent with the bundle classes + return Isis::Null; + } + } + + + /** + * This method returns an angular measure in radians of a distance in the direction + * of and relative to the longitude of the SurfacePoint. It should only be used to + * convert lengths relative to the SurfacePoint and in the direction of longitude. + * Typical usage is to convert longitude sigmas and point corrections for the + * SurfacePoint. + * + * @param lonLength The delta longitude distance in meters to convert to radians + * @return @b LonDistAngle The converted delta length in radians + * + */ + double SurfacePoint::MetersToLongitude(double deltaLonMeters) { + + if (Valid() && !IsSpecial(deltaLonMeters)) { + double convFactor = cos((double)GetLatitude().radians()); + double deltaLonRadians; + + // Convert angle displacement to radians relative to longitude of SurfacePoint. + if (convFactor > DBL_EPSILON) { + deltaLonRadians = deltaLonMeters / (convFactor*GetLocalRadius().meters()); + } + else { + // Brent Archinal suggested setting sigma to pi in the case of a point near the pole + deltaLonRadians = PI; + } + return deltaLonRadians; + } + else { + // Return Null to be consistent with the bundle classes + return Isis::Null; + } + } + + + /** + * This method returns a Displacement of an Angle relative to the current + * SurfacePoint latitude. It should only be used to convert relative latitudes + * near the SurfacePoint latitude. Typical usage would be to convert + * latitude sigmas and point corrections for the SurfacePoint. + * + * @param latRadians The latitude in Angle units to convert to Displacement units + * @return @b LatDisp The converted latitude in displacement units at the + * SurfacePoint latitude + * + */ + double SurfacePoint::LatitudeToMeters(double relativeLat) const { + // Returns are consistent with the bundle classes + if (relativeLat == 0.) { + return 0.; + } + else if (Valid() && !IsSpecial(relativeLat) && GetLocalRadius().isValid() ) { + return relativeLat * GetLocalRadius().meters(); + } + else { + return Isis::Null; + } + } + + + /** + * This method returns a length in meters version of a delta longitude angle + * in radians relative to the current SurfacePoint longitude. It should only be + * used to convert delta longitudes relative to the SurfacePoint longitude. + * Typical usage would be to convert longitude sigmas and point corrections + * for the SurfacePoint. + * + * @param lonRadians The delta longitude in radians to convert to meters + * @return @b relativeLonDist The delta longitude in meters from the + * SurfacePoint longitude + * + */ + double SurfacePoint::LongitudeToMeters(double deltaLonRadians) const{ + // Returns are consistent with the bundle classes + double deltaLonMeters = Isis::Null; + + if (deltaLonRadians == 0.) { + deltaLonMeters = 0.; + } + else if (Valid() && !IsSpecial(deltaLonRadians) && GetLocalRadius().isValid() ) { + // Convert from radians to meters and return + double scalingRadius = cos(GetLatitude().radians()) * GetLocalRadius().meters(); + deltaLonMeters = deltaLonRadians * scalingRadius; + } + + return deltaLonMeters; + } + + + /** + * This method converts the given string value to a SurfacePoint::CoordinateType + * enumeration. Currently (March 31, 2017) accepted inputs are listed below. + * This method is case insensitive. + * + * @param type The coordinate type name to be converted + * @return @b CoordinateType The enumeration corresponding to the input name + * + */ + SurfacePoint::CoordinateType + SurfacePoint::stringToCoordinateType(QString type) { + if (type.compare("LATITUDINAL", Qt::CaseInsensitive) == 0) { + return SurfacePoint::Latitudinal; + } + else if (type.compare("RECTANGULAR", Qt::CaseInsensitive) == 0) { + return SurfacePoint::Rectangular; + } + else { + throw IException(IException::Programmer, + "Unknown coordinate type for a SurfacePoint [" + type + "].", + _FILEINFO_); + } + } + + + /** + * Converts the given SurfacePoint::CoordinateType enumeration to a string. + * This method is used to print the type of control point coordinates used in + * the bundle adjustment. + * + * @param type The Coordinate Type enumeration to be converted. + * + * @return @b QString The name associated with the given CoordinateType. + * + * @throw Isis::Exception::Programmer "Unknown SurfacePoint CoordinateType enum." + */ + QString SurfacePoint::coordinateTypeToString( + SurfacePoint::CoordinateType type) { + switch (type) { + + case Latitudinal: + return "Latitudinal"; + break; + + case Rectangular: + return "Rectangular"; + break; + + default: + IString msg ="Unknown surface point coordinate type enum [" + toString(type) + "]." ; + throw IException(IException::Programmer, msg, _FILEINFO_); + } + } + + + /** + * This method returns a double version of a Longitude in the specified units + * + * @param lon The longitude to convert to a double + * @param units The units in which to return the longitude (see CoordinateUnits in .h file) + * + */ + double SurfacePoint::LonToDouble(Longitude lon, CoordUnits units) { + double value; + + switch (units) { + + case Radians: + value = GetLongitude().radians(); + break; + + case Degrees: + value = GetLongitude().degrees(); + break; + + default: + IString msg = "Invalid unit for longitude (must be Radians of Degrees)."; + throw IException(IException::Programmer, msg, _FILEINFO_); + } + return value; + } + + Displacement SurfacePoint::GetX() const { if(!p_x) return Displacement(); @@ -768,32 +1446,187 @@ namespace Isis { Distance SurfacePoint::GetXSigma() const { if(!p_rectCovar) return Distance(); - return Distance(sqrt((*p_rectCovar)(0, 0)), Distance::Meters); + return Distance(sqrt((*p_rectCovar)(0, 0)), Distance::Kilometers); } Distance SurfacePoint::GetYSigma() const { if(!p_rectCovar) return Distance(); - return Distance(sqrt((*p_rectCovar)(1, 1)), Distance::Meters); + return Distance(sqrt((*p_rectCovar)(1, 1)), Distance::Kilometers); } Distance SurfacePoint::GetZSigma() const { if(!p_rectCovar) return Distance(); - return Distance(sqrt((*p_rectCovar)(2, 2)), Distance::Meters); + return Distance(sqrt((*p_rectCovar)(2, 2)), Distance::Kilometers); + } + + + /** + * This method returns the weight of a SurfacePoint coordinate + * Note: At this time a units argument is not included. If BundleAdjust + * is modified to allow different distance or displacement units + * other than kilometers, the units argument can be added similar + * to the GetCoord and GetSigma methods. Angle weights are in + * 1/rad^2 and distance and displacements are in 1/km^2 + * + * @param type The coordinate type to return (see CoordinateType in .h file) + * @param index The coordinate index to return (1 <= index <= 3) + * + * + */ + double SurfacePoint::GetWeight(CoordinateType type, CoordIndex index) { + double value = 0; // See first TODO in GetCoord + + switch (type) { + + case Latitudinal: + + switch (index) { + + case One: + value = GetLatWeight(); // 1/radians**2 + break; + + case Two: + value = GetLonWeight(); // 1/radians**2 + break; + + case Three: + value = GetLocalRadiusWeight(); // 1/km**2 + break; + + default: + IString msg = "Invalid coordinate index (must be less than 3)."; + throw IException(IException::Programmer, msg, _FILEINFO_); + } + break; + + case Rectangular: + + switch (index) { + + case One: + value = GetXWeight(); // 1/km**2 + break; + + case Two: + value = GetYWeight(); // 1/km**2 + break; + + case Three: + value = GetZWeight(); // 1/km**2 + break; + + default: + IString msg = "Invalid coordinate index (must be less than 3)."; + throw IException(IException::Programmer, msg, _FILEINFO_); + } + break; + + default: + IString msg ="Unknown surface point coordinate type enum [" + toString(type) + "]." ; + throw IException(IException::Programmer, msg, _FILEINFO_); + } + return value; + } + + + /** + * Return X weight for bundle adjustment + * Units are 1/(kilometers)^2 + * + */ + double SurfacePoint::GetXWeight() const { + + double dXSigma = GetXSigma().kilometers(); + + if (dXSigma <= 0.0 ) { + IString msg = "SurfacePoint::GetXWeight(): Sigma <= 0.0"; + throw IException(IException::Programmer, msg, _FILEINFO_); + } + + return 1.0/(dXSigma*dXSigma); + } + + + /** + * Return Y weight for bundle adjustment + * Units are 1/(kilometers)^2 + * + */ + double SurfacePoint::GetYWeight() const { + + double dYSigma = GetYSigma().kilometers(); + + if (dYSigma <= 0.0 ) { + IString msg = "SurfacePoint::GetYWeight(): Sigma <= 0.0"; + throw IException(IException::Programmer, msg, _FILEINFO_); + } + + return 1.0/(dYSigma*dYSigma); + } + + + /** + * Return Z weight for bundle adjustment + * Units are 1/(kilometers)^2 + * + */ + double SurfacePoint::GetZWeight() const { + + double dZSigma = GetZSigma().kilometers(); + + if (dZSigma <= 0.0 ) { + IString msg = "SurfacePoint::GetZWeight(): Sigma <= 0.0"; + throw IException(IException::Programmer, msg, _FILEINFO_); + } + + return 1.0/(dZSigma*dZSigma); } - symmetric_matrix SurfacePoint::GetRectangularMatrix() - const { + symmetric_matrix SurfacePoint::GetRectangularMatrix + (SurfacePoint::CoordUnits units) const { if(!p_rectCovar) { symmetric_matrix tmp(3); tmp.clear(); return tmp; } + // Make sure the units are valid + if (units != Kilometers && units != Meters) { + IString msg = "Units must be Kilometers or Meters"; + throw IException(IException::Programmer, msg, _FILEINFO_); + } + + symmetric_matrix covar(3); + covar.clear(); + + switch (units) { + + case Meters: + // Convert member matrix to Meters to return + covar(0,0) = (*p_rectCovar)(0,0)*1.0e6; + covar(0,1) = (*p_rectCovar)(0,1)*1.0e6; + covar(0,2) = (*p_rectCovar)(0,2)*1.0e6; + covar(1,1) = (*p_rectCovar)(1,1)*1.0e6; + covar(1,2) = (*p_rectCovar)(1,2)*1.0e6; + covar(2,2) = (*p_rectCovar)(2,2)*1.0e6; + return covar; + break; + + case Kilometers: + return *p_rectCovar; + break; + + default: + IString msg = "Unrecognized unit for a Displacement (must be meters or kilometers)."; + throw IException(IException::Programmer, msg, _FILEINFO_); + } + return *p_rectCovar; } @@ -891,24 +1724,18 @@ namespace Isis { /** - * Return the latitude sigma in meters + * Return the latitude sigma as a Distance * */ Distance SurfacePoint::GetLatSigmaDistance() const { - Distance latSigmaDistance = Distance(); - - if(Valid()) { - Angle latSigma = GetLatSigma(); - - if (latSigma.isValid() && GetLocalRadius().isValid()) { - // Distance scalingRadius = GetLocalRadius(); + double d = LatitudeToMeters(GetLatSigma().radians()); - // Convert from radians to meters - latSigmaDistance = latSigma.radians() * GetLocalRadius(); - } + if (d > DBL_EPSILON) { + return Distance(d, Distance::Meters); + } + else { + return Distance(); } - - return latSigmaDistance; } @@ -916,23 +1743,16 @@ namespace Isis { * Return the longitude sigma in meters * */ - Distance SurfacePoint::GetLonSigmaDistance() const { - Distance lonSigmaDistance; - - if(Valid()) { - Angle lonSigma = GetLonSigma(); - - if (lonSigma.isValid()) { - Distance scalingRadius = cos(GetLatitude().radians()) * GetLocalRadius(); - - // Convert from radians to meters and return - // TODO What do we do when the scaling radius is 0 (at the pole)? - if (scalingRadius.meters() != 0.) - lonSigmaDistance = lonSigma.radians() * scalingRadius; - } - } - - return lonSigmaDistance; + Distance SurfacePoint::GetLonSigmaDistance() const{ + // return lonSigmaDistance; + double d = LongitudeToMeters(GetLonSigma().radians()); +// TODO What do we do when the scaling radius is 0 (at the pole)? + // if (d > DBL_EPSILON) { + return Distance(d, Distance::Meters); + // } + // else { // Too close to the pole + // return Distance(); + // } } @@ -940,17 +1760,49 @@ namespace Isis { if(!p_sphereCovar) return Distance(); - return Distance(sqrt((*p_sphereCovar)(2, 2)), Distance::Meters); + return Distance(sqrt((*p_sphereCovar)(2, 2)), Distance::Kilometers); } - symmetric_matrix SurfacePoint::GetSphericalMatrix() const { + symmetric_matrix SurfacePoint::GetSphericalMatrix + (SurfacePoint::CoordUnits units) const { if(!p_sphereCovar) { symmetric_matrix tmp(3); tmp.clear(); return tmp; } + // Make sure the units are valid + if (units != Kilometers && units != Meters) { + IString msg = "Units must be Kilometers or Meters"; + throw IException(IException::Programmer, msg, _FILEINFO_); + } + + symmetric_matrix covar(3); + covar.clear(); + + switch (units) { + + case Meters: + // Convert member matrix to Meters to return + covar(0,0) = (*p_sphereCovar)(0,0); + covar(0,1) = (*p_sphereCovar)(0,1); + covar(0,2) = (*p_sphereCovar)(0,2)*1000.; + covar(1,1) = (*p_sphereCovar)(1,1); + covar(1,2) = (*p_sphereCovar)(1,2)*1000.; + covar(2,2) = (*p_sphereCovar)(2,2)*1.0e6; + return covar; + break; + + case Kilometers: + return *p_sphereCovar; + break; + + default: + IString msg = "Unrecognized unit for a Displacement (must be meters or kilometers)."; + throw IException(IException::Programmer, msg, _FILEINFO_); + } + return *p_sphereCovar; } @@ -989,7 +1841,7 @@ namespace Isis { /** * Return radius weight for bundle adjustment - * Units are 1/(meters)^2 + * Units are 1/(kilometers)^2 * */ double SurfacePoint::GetLocalRadiusWeight() const { diff --git a/isis/src/base/objs/SurfacePoint/SurfacePoint.h b/isis/src/base/objs/SurfacePoint/SurfacePoint.h index 0c8e27776a4e13a7573ba34476357647fb05749f..39833cb964cd3af894a8756fbee58910ec2e4650 100644 --- a/isis/src/base/objs/SurfacePoint/SurfacePoint.h +++ b/isis/src/base/objs/SurfacePoint/SurfacePoint.h @@ -25,9 +25,13 @@ #include #include +// Qt library +#include + #include "boost/numeric/ublas/symmetric.hpp" #include "boost/numeric/ublas/io.hpp" +// ISIS library #include "Displacement.h" #include "Distance.h" #include "Angle.h" @@ -100,10 +104,67 @@ namespace Isis { * and cleaned up documentation. Changed localRadius member * from a pointer to value to reduce extraneous if blocks. * References #5457 + * @history 2018-09-06 Debbie A. Cook - Originally added to BundleXYZ branch on + * 2017-06-25 - Added CoordinateType, CoordUnits, and CoordIndex + * to support new convenience methods GetCoord, GetSigma, and GetWeight. + * Also added methods GetXWeight, GetYWeight, GetZWeight, LatToDouble, + * LonToDouble, DistanceToDouble, DisplacementToDouble, + * getCoordSigmaDistance, stringToCoordinateType, and + * coordinateTypeToString. Fixed comment in GetLocalRadiusWeight method + * to indicate kilometers instead of meters. References #4649 and #501. + * @history 2018-09-06 Debbie A. Cook - Originally added to BundleXYZ branch on + * 2017-07-25 - Corrected covar(2,2) units in SetSphericalSigmas, + * and all diagonal units in SetRectangularSigmas. Corrected spelling + * of equatorial in comments. Corrected conversion of longitude sigma + * from meters to radians in SetSphericalSigmasDistance and from radians + * to meters in GetLonSigmaDistance. Fixed SetRectangularMatrix to take + * input in km instead of m. + * @history 2018-09-06 Debbie A. Cook - Originally added to BundleXYZ branch on + * 2017-11-20 - Added an additional argument to SetRectangularMatrix + * and SetSphericalMatrix to specify the units of the matrix. This will allow the + * bundle adjust to set in km and existing software to continue setting in the default + * units (meters). The matrix will be stored in km in this object to avoid extra + * conversions during processing. + * @history 2018-09-06 Debbie A. Cook - Originally added to BundleXYZ branch on + * 2018-03-07 - Added an additional argument to GetRectangularMatrix + * and GetSphericalMatrix to specify the units of the matrix. This will allow existing + * callers to get in m (the default) and bundle adjust software to get in km and + * minimize conversions. The matrix is held in this object in km to avoid extra + * conversions during the bundle adjustment. The control net stores the distance + * values of the matrix in m**2. + * @history 2018-09-20 Debbie A. Cook - Added new methods + * LatitudeToMeters, MetersToLatitude, + * LongitudeToMeters, and MetersToLongitude + * for converting sigmas and corrections at the current SurfacePoint + * coordinates. References #4649 and #501. + * @history 2018-10-12 Debbie A. Cook - Initialized local radius in + * SetRectangularCoordinates + * */ class SurfacePoint { public: + + // definitions + /** + * Defines the coordinate typ, units, and coordinate index for some of the output methods + */ + enum CoordinateType { + Latitudinal, /**< Planetocentric latitudinal (lat/lon/rad) coordinates */ + Rectangular /**< Body-fixed rectangular x/y/z coordinates */ + }; + enum CoordUnits { + Degrees, + Kilometers, + Meters, + Radians + }; + enum CoordIndex { + One=0, + Two=1, + Three=2 + }; + // Constructors SurfacePoint(); SurfacePoint(const SurfacePoint &other); @@ -135,13 +196,16 @@ namespace Isis { void SetRectangular(const Displacement x, const Displacement y, const Displacement z, const boost::numeric::ublas::symmetric_matrix& covar); + void SetRectangularCoordinates(const Displacement &x, const Displacement &y, + const Displacement &z); + //! Set surface point and sigmas in rectangular coordinates and convert to planetocentric void SetRectangularSigmas(const Distance &xSigma, const Distance &ySigma, const Distance &zSigma); - void SetRectangularMatrix( - const boost::numeric::ublas::symmetric_matrix& covar); + const boost::numeric::ublas::symmetric_matrix& covar, + SurfacePoint::CoordUnits units = SurfacePoint::Meters); // Spherical loading utilities @@ -161,7 +225,8 @@ namespace Isis { const Distance &radius); void SetSphericalMatrix( - const boost::numeric::ublas::symmetric_matrix& covar); + const boost::numeric::ublas::symmetric_matrix& covar, + SurfacePoint::CoordUnits units = SurfacePoint::Meters); void SetSphericalSigmas(const Angle &latSigma, const Angle &lonSigma, const Distance &radiusSigma); @@ -172,16 +237,35 @@ namespace Isis { void ResetLocalRadius(const Distance &radius); bool Valid() const; - + +// Generic utilities for convenience + + //! Set the covariance matrix + void SetMatrix(CoordinateType type, + const boost::numeric::ublas::symmetric_matrix& covar); + + //! Compute partial derivative of conversion from body-fixed coordinates to the specified + // coordinate type with respect to the indicated coordinate (specified by index). + std::vector Partial(CoordinateType type, CoordIndex index); + // Output methods + double GetCoord(CoordinateType type, CoordIndex index, CoordUnits units); + // Consider making this GetSigmaDistance and use the Distance methods to specify units for + // maximum flexibility and safety. ***TBD*** + double GetSigma(CoordinateType type, CoordIndex index, CoordUnits units); + Distance GetSigmaDistance(CoordinateType type, CoordIndex index); + double GetWeight(CoordinateType type, CoordIndex index); Displacement GetX() const; Displacement GetY() const; Displacement GetZ() const; Distance GetXSigma() const; Distance GetYSigma() const; Distance GetZSigma() const; + double GetXWeight() const; + double GetYWeight() const; + double GetZWeight() const; boost::numeric::ublas::symmetric_matrix - GetRectangularMatrix() const; + GetRectangularMatrix(SurfacePoint::CoordUnits units = SurfacePoint::Meters) const; Latitude GetLatitude() const; Longitude GetLongitude() const; Distance GetLocalRadius() const; @@ -194,12 +278,27 @@ namespace Isis { Distance GetLocalRadiusSigma() const; double GetLocalRadiusWeight() const; boost::numeric::ublas::symmetric_matrix - GetSphericalMatrix() const; + GetSphericalMatrix + (SurfacePoint::CoordUnits units = SurfacePoint::Meters) const; +// Conversion methods (for convenience) + double DisplacementToDouble(Displacement disp, CoordUnits units); + double DistanceToDouble(Distance dist, CoordUnits units); + double MetersToLatitude(double latLength); + double MetersToLongitude(double lonLength); + double LatitudeToMeters(double latitude) const; + double LongitudeToMeters(double longitude) const; + double LatToDouble(Latitude lat, CoordUnits units); + double LonToDouble(Longitude lon, CoordUnits units); + static CoordinateType stringToCoordinateType(QString type); + static QString coordinateTypeToString(CoordinateType type); + // Computational methods Distance GetDistanceToPoint(const SurfacePoint &other) const; Distance GetDistanceToPoint(const SurfacePoint &other, const Distance &sphereRadius) const; + std::vector LatitudinalDerivative(CoordIndex index); + std::vector RectangularDerivative(CoordIndex index); // Misc methods void ToNaifArray(double naifOutput[3]) const; diff --git a/isis/src/base/objs/SurfacePoint/SurfacePoint.truth b/isis/src/base/objs/SurfacePoint/SurfacePoint.truth index e1361aadda912913899883e41c4726193e481261..17607a0ee4b883f9e34402ec2816c41476092a8a 100644 --- a/isis/src/base/objs/SurfacePoint/SurfacePoint.truth +++ b/isis/src/base/objs/SurfacePoint/SurfacePoint.truth @@ -1,6 +1,6 @@ UnitTest for SurfacePoint -1-Test rectangular set of point and variance only ... +1-Test rectangular set of point and variance only (variance in m^2) ... with x=-424.024048 m, y=734.4311949 m, z=529.919264 m,sigmaX=10. m, sigmaY=50. m, sigmaZ=20. m Output spherical... @@ -10,52 +10,120 @@ UnitTest for SurfacePoint latitude sigma=0.0286569649 radians, longitude sigma=0.0311981281 radians, radius sigma=38.4548873 m latitude sigma=28.6569649 m, longitude sigma=26.4575131 m, radius sigma=38.4548873 m latitude weight =1217.69806, longitude weight =1027.40796, radius weight =676.233861 - spherical covariance matrix = 0.00082122164 0.000649383279 -0.674095535 - 0.000649383279 0.000973323195 -1.03923048 - -0.674095535 -1.03923048 1478.77836 + spherical covariance matrix = 0.00082122164 0.000649383279 -0.000674095535 + 0.000649383279 0.000973323195 -0.00103923048 + -0.000674095535 -0.00103923048 0.00147877836 Input rectangular sigmas = 10/50/20 -2-Testing spherical set of point and variance/covariance matrix ... +2-Testing spherical set of point and variance/covariance matrix (in meters^2)... with lat=32 degrees, lon=120 degrees, radius=1000 m - latitude sigma=1.64192315 m, longitude sigma=1.78752107 m, radiusSig=38.4548873 m + latitude sigma=1.64192315 deg, longitude sigma=1.78752107 deg, radiusSig=38.4548873 m Output rectangular... x=-424.024048 m, y=734.431195 m, z=529.919264 m X sigma=10 m, Y sigma=50 m, Z sigma=20 m - rectangular covariance matrix = 100 0 0 - 0 2500 0 - 0 0 400 + rectangular covariance matrix = 0.0001 0 0 + 0 0.0025 0 + 0 0 0.0004 3-Testing rectangular set with point and sigmas only... Output spherical... lat=32 degrees, lon=120 degrees, radius=1000m latitude sigma=1.64192315 degrees, longitude sigma=1.78752107 degrees, radius sigma=38.4548873m - ocentric covariance matrix = 0.00082122164 0.000649383279 -0.674095535 - 0.000649383279 0.000973323195 -1.03923048 - -0.674095535 -1.03923048 1478.77836 + ocentric covariance matrix = 0.00082122164 0.000649383279 -0.000674095535 + 0.000649383279 0.000973323195 -0.00103923048 + -0.000674095535 -0.00103923048 0.00147877836 -4-Testing planetocentric set with point and sigmas only in degrees ... +4-Testing planetocentric set with point and sigmas ... 4a-Output rectangular from degrees... x=-424.024048 m, y=734.431195 m, z=529.919264 m X sigma =29.1295681 m, Y sigma = 33.8466425 m, Z sigma = 31.7155018m - rectangular covariance matrix = 848.531739 -257.264514 -147.752015 - -257.264514 1145.59521 255.913997 - -147.752015 255.913997 1005.87306 + rectangular covariance matrix = 0.000848531739 -0.000257264514 -0.000147752015 + -0.000257264514 0.00114559521 0.000255913997 + -0.000147752015 0.000255913997 0.00100587306 4b-Output rectangular from radians... x=-424.024046 m, y=734.431196 m, z=529.919264 m X sigma = 29.1295681 m, Y sigma = 33.8466425 m, Z sigma = 31.7155018m - rectangular covariance matrix = 848.531737 -257.264513 -147.752014 - -257.264513 1145.59521 255.913997 - -147.752014 255.913997 1005.87305 + rectangular covariance matrix = 0.000848531737 -0.000257264513 -0.000147752014 + -0.000257264513 0.00114559521 0.000255913997 + -0.000147752014 0.000255913997 0.00100587305 + 4c-Output spherical sigmas from meters... + latitude sigma=0.0286569649 radians, longitude sigma=0.031198128 radians, radius sigma=38.4548873 m 5-Testing copy constructor Output spherical... lat=32 degrees, lon=120 degrees, radius=1000 m latitude sigma = 1.64192315 degrees, longitude sigma = 1.78752107 degrees, radius sigma = 38.4548873 m - ocentric covariance matrix = 0.00082122164 0.000649383279 -0.674095535 - 0.000649383279 0.000973323195 -1.03923048 - -0.674095535 -1.03923048 1478.77836 + ocentric covariance matrix = 0.00082122164 0.000649383279 -0.000674095535 + 0.000649383279 0.000973323195 -0.00103923048 + -0.000674095535 -0.00103923048 0.00147877836 Testing Longitude Accessor... Longitude (from -45): 315 +6-Testing set of matrices in spherical and rectangular coordinates in km ... + 6a-Test rectangular set of point and variance only (variance in km^2) ... + with x=-424.024048 m, y=734.4311949 m, z=529.919264 m,sigmaX=.01 km, sigmaY=.05 km, sigmaZ=.02 km + + Output spherical... + lat = 32 degrees, lon = 120 degrees, radius = 1000 meters + lat = 0.55850536 radians, lon = 2.0943951 radians, radius = 1000 meters + latitude sigma=0.0286569649 radians, longitude sigma=0.0311981281 radians, radius sigma=38.4548873 m + spherical covariance matrix = 0.00082122164 0.000649383279 -0.000674095535 + 0.000649383279 0.000973323195 -0.00103923048 + -0.000674095535 -0.00103923048 0.00147877836 + Input rectangular sigmas = 0.01/0.05/0.02 + + 6b-Testing spherical set of point and variance/covariance matrix (in km^2)... + with lat=32 degrees, lon=120 degrees, radius=1000 m + latitude sigma=1.64192315 deg, longitude sigma=1.78752107 deg, radiusSig=38.4548873 m + Output rectangular... + x=-424.024048 m, y=734.431195 m, z=529.919264 m + X sigma=10 m, Y sigma=50 m, Z sigma=20 m + rectangular covariance matrix = 0.0001 0 0 + 0 0.0025 0 + 0 0 0.0004 + +Testing error conditions in GetCoord, GetSigma, GetWeight, LatToDouble, +LonToDouble, GetSigmaDistance, DistanceToDouble, and DisplacementToDouble... + + ...Test Rectangular GetCoord with incorrect unit Degrees +**PROGRAMMER ERROR** Unrecognized unit for a Displacement (must be meters or kilometers). + ...Test Rectangular GetCoord with incorrect unit Radians +**PROGRAMMER ERROR** Unrecognized unit for a Displacement (must be meters or kilometers). + ...Test Rectangular GetCoord with incorrect unit Degrees +**PROGRAMMER ERROR** Unrecognized unit for a Distance (not meters or kilometers). + ...Test Latitudinal GetCoord with incorrect unit Radians for local radius +**PROGRAMMER ERROR** Unrecognized unit for a Distance (not meters or kilometers). + ...Test Latitudinal GetCoord with incorrect unit Kilometers for latitude +**PROGRAMMER ERROR** Invalid unit for latitude (must be Radians or Degrees). + ...Test Latitudinal GetCoord with incorrect unit Meters for longitude +**PROGRAMMER ERROR** Invalid unit for longitude (must be Radians of Degrees). + +Test error statements: case where weights are requested after only coordinates have been set... +**PROGRAMMER ERROR** SurfacePoint::GetXWeight(): Sigma <= 0.0. + +Test error statements: case of invalid SurfacePoint in SetSphericalSigmasDistance +**PROGRAMMER ERROR** Cannot set spherical sigmas on an invalid surface point. + +...Testing GetCoord, GetSigma, and GetWeight... + +Rectangular Coordinates kilometers: X= -0.424024048 Y = 0.734431195 Z = 0.529919264 +Rectangular Coordinates meters: X= -424.024048 Y = 734.431195 Z = 529.919264 +Rectangular sigmas kilometers: X= 0.01 Y = 0.05 Z = 0.02 +Using GetSigmaDistance, Rectangular sigmas kilometers: X= 0.01 Y = 0.05 Z = 0.02 +Rectangular sigmas meters: X= 10 Y = 50 Z = 20 +Using GetSigmaDistance, Rectangular sigmas meters: X= 10 Y = 50 Z = 20 +Rectangular Weights kilometers: X = 10000 Y = 400 Z = 2500 +Latitudinal Coordinates radians: Latitude= 0.55850536 Longitude = 2.0943951 Local Radius = 1 +Latitudinal Coordinates degrees: Latitude= 32 Longitude = 120 Local Radius = 1000 +Latitudinal weight degrees: Latitude= 1217.69806 Longitude = 1027.40796 Local Radius = 676.233861 + +Testing stringToCoordinateType with Latitudinal: coordType = 0 +Testing coordinateTypeToString with coordType = 0: coordTypeStr = Latitudinal +Testing stringToCoordinateType with Rectangular: coordType = 1 +Testing coordinateTypeToString with coordType = 1: coordTypeStr = Rectangular + +Test invalid coordinate type error condition. +**PROGRAMMER ERROR** Unknown coordinate type for a SurfacePoint [Garbage]. + Test computational methods... SphericalDistanceToPoint (i.e. haversine): 1570.79633 meters diff --git a/isis/src/base/objs/SurfacePoint/unitTest.cpp b/isis/src/base/objs/SurfacePoint/unitTest.cpp index 4696b50dacc3fb0d5ac5c79b53d0bd87e8ab9252..6907b8bb514a861638b0064f063696f6994ad37a 100644 --- a/isis/src/base/objs/SurfacePoint/unitTest.cpp +++ b/isis/src/base/objs/SurfacePoint/unitTest.cpp @@ -12,7 +12,7 @@ #include "Preference.h" #include "SurfacePoint.h" -#include "boost/numeric/ublas/symmetric.hpp" +#include using namespace Isis; using namespace std; @@ -27,6 +27,19 @@ using namespace boost::numeric::ublas; * latitude, longitude and radius weight accessor methods. * @history 2018-06-28 Debbie A.Cook - Removed test of obsolete method * SetRadii + * @history 2018-09-06 (added to BundleXYZ branch on 2017-05-27) + * Debbie A. Cook - Added tests for new methods: + * GetCoord, GetSigma, GetWeight, GetXSigma, GetYSigma, + * GetZsigma, LatToDouble, LonToDouble, DistanceToDouble, + * DisplacementToDouble, and enum types CoordinateType, + * CoordUnits, and CoordIndex. Fixed incorrect units in report for + * latSig and lonSig. + * @history 2018-09-06 (added to BundleXYZ branch on 2017-11-20) + * Debbie A. Cook - Added tests for new options in + * SetRectangularMatrix and SetSphericalMatrix. + * @history 2018-09-21 Debbie A. Cook - Added tests for new + * SurfacePoint modifications. + * */ int main(int argc, char *argv[]) { Isis::Preference::Preferences(true); @@ -34,7 +47,7 @@ int main(int argc, char *argv[]) { try { cout << "UnitTest for SurfacePoint" << endl << endl; - cout << "1-Test rectangular set of point and variance only ..." << endl; + cout << "1-Test rectangular set of point and variance only (variance in m^2) ..." << endl; cout << " with x=-424.024048 m, y=734.4311949 m, z=529.919264 m," "sigmaX=10. m, sigmaY=50. m, sigmaZ=20. m" << endl << endl; Isis::SurfacePoint spRec; @@ -42,10 +55,12 @@ int main(int argc, char *argv[]) { symmetric_matrix covar; // Units are m**2 covar.resize(3); covar.clear(); + // Units are m**2 covar(0,0) = 100.; covar(1,1) = 2500.; covar(2,2) = 400.; + // Default is to set covar in meters**2 for length units spRec.SetRectangular(Displacement(-424.024048, Displacement::Meters), Displacement(734.4311949, Displacement::Meters), Displacement(529.919264, Displacement::Meters), covar); @@ -56,9 +71,11 @@ int main(int argc, char *argv[]) { double latSig = spRec.GetLatSigma().degrees(); double lonSig = spRec.GetLonSigma().degrees(); double radSig = spRec.GetLocalRadiusSigma().meters(); +; symmetric_matrix covarSphere(3); covarSphere.clear(); - covarSphere = spRec.GetSphericalMatrix(); + // Default is to get matrix with length units in meters**2 + covarSphere = spRec.GetSphericalMatrix(SurfacePoint::Kilometers); cout << setprecision(9); cout << " Output spherical..." << endl; @@ -95,20 +112,26 @@ int main(int argc, char *argv[]) { cout << endl; - cout << "2-Testing spherical set of point and variance/covariance matrix ..." - << endl; + cout << "2-Testing spherical set of point and variance/covariance matrix (in meters^2)..." + << endl; + // Usage note: In order to get accurate results, the full correlation matrix should be + // used as opposed to only setting the diagonal elements with the sigmas. cout << " with lat=" << lat << " degrees, lon=" << lon << " degrees, radius=" << radius << " m" << endl; - cout << " latitude sigma=" << latSig << " m, longitude sigma=" << lonSig - << " m, radiusSig=" << radSig << " m" << endl; + cout << " latitude sigma=" << latSig << " deg, longitude sigma=" << lonSig + << " deg, radiusSig=" << radSig << " m" << endl; Isis::SurfacePoint spSphere; + // Convert covarSphere to meters to be able to test default set + covarSphere(0,2) *= 1000.; + covarSphere(1,2) *= 1000.; + covarSphere(2,2) *= 1.0e6; spSphere.SetSpherical(Latitude(lat, Angle::Degrees), Longitude(lon, Angle::Degrees), Distance(radius, Distance::Meters), - covarSphere ); + covarSphere); symmetric_matrix covarRec(3); covarRec.clear(); - covarRec = spSphere.GetRectangularMatrix(); + covarRec = spSphere.GetRectangularMatrix(SurfacePoint::Kilometers); if(fabs(covarRec(0,1)) < 1E-12) covarRec(0,1) = 0.0; if(fabs(covarRec(0,2)) < 1E-12) covarRec(0,2) = 0.0; @@ -155,7 +178,7 @@ int main(int argc, char *argv[]) { double radSig = spRec.GetLocalRadiusSigma().meters(); symmetric_matrix covarSphere(3); covarSphere.clear(); - covarSphere = spRec.GetSphericalMatrix(); + covarSphere = spRec.GetSphericalMatrix(SurfacePoint::Kilometers); cout << setprecision(9); cout << " Output spherical..." << endl; @@ -174,25 +197,32 @@ int main(int argc, char *argv[]) { // The next test will not match previous results because only the sigmas are set // and not the whole variance/covariance matrix cout << endl; - cout << "4-Testing planetocentric set with point and sigmas only in degrees ..." + cout << "4-Testing planetocentric set with point and sigmas ..." << endl; - Isis::SurfacePoint spSphere1,spSphere2; + Isis::SurfacePoint spSphere1,spSphere2,spSphere4; spSphere1.SetSpherical(Latitude(32., Angle::Degrees), Longitude(120., Angle::Degrees), Distance(1000., Distance::Meters), Angle(1.64192315,Angle::Degrees), Angle(1.78752107, Angle::Degrees), - Distance(38.454887335682053718134171237789, + Distance( 38.454887335682053718134171237789, Distance::Meters)); symmetric_matrix covarRec(3); covarRec.clear(); - covarRec = spSphere1.GetRectangularMatrix(); + covarRec = spSphere1.GetRectangularMatrix(SurfacePoint::Kilometers); spSphere2.SetSpherical(Latitude(0.55850536, Angle::Radians), Longitude(2.0943951, Angle::Radians), Distance(1000., Distance::Meters), Angle(0.028656965, Angle::Radians), Angle(0.0311981281, Angle::Radians), Distance(38.4548873, Distance::Meters)); + spSphere4.SetSpherical(Latitude(0.55850536, Angle::Radians), + Longitude(2.0943951, Angle::Radians), + Distance(1000., Distance::Meters)); + spSphere4.SetSphericalSigmasDistance( + Distance(28.6569649, Distance::Meters), + Distance(26.4575131, Distance::Meters), + Distance(38.4548873, Distance::Meters)); // TODO try to convert ocentric sigmas to meters and get error to test error @@ -212,7 +242,7 @@ int main(int argc, char *argv[]) { << covarRec(2,1) << " " << covarRec(2,2) << endl; covarRec.clear(); - covarRec = spSphere2.GetRectangularMatrix(); + covarRec = spSphere2.GetRectangularMatrix(SurfacePoint::Kilometers); cout << " 4b-Output rectangular from radians..." << endl; cout << " x=" << spSphere2.GetX().meters() << " m, y=" << spSphere2.GetY().meters() @@ -227,9 +257,13 @@ int main(int argc, char *argv[]) { << covarRec(1,1) << " " << covarRec(1,2) << endl; cout << " " << covarRec(2,0) << " " << covarRec(2,1) << " " << covarRec(2,2) << endl; - - + cout << " 4c-Output spherical sigmas from meters..." << endl; + cout << " latitude sigma=" << spSphere4.GetLatSigma().radians() << + " radians, longitude sigma=" << spSphere4.GetLonSigma().radians() + << " radians, radius sigma=" << spSphere4.GetLocalRadiusSigma().meters() + << " m" << endl; cout << endl << "5-Testing copy constructor" << endl; + Isis::SurfacePoint spRec2(spSphere1); lat = (spRec2.GetLatitude()).degrees(); lon = (spRec2.GetLongitude()).degrees(); @@ -257,11 +291,339 @@ int main(int argc, char *argv[]) { cout << "Longitude (from -45): " << spSphere3.GetLongitude().degrees() << endl << endl; + cout << "6-Testing set of matrices in spherical and rectangular coordinates in km ..." + << endl; + cout << " 6a-Test rectangular set of point and variance only (variance in km^2) ..." << endl; + cout << " with x=-424.024048 m, y=734.4311949 m, z=529.919264 m," + "sigmaX=.01 km, sigmaY=.05 km, sigmaZ=.02 km" << endl << endl; + Isis::SurfacePoint spRecKm; + + // spRecKm.SetRadii(Distance(1000., Distance::Meters), + // Distance(1000., Distance::Meters), + // Distance(1000., Distance::Meters)); + + symmetric_matrix covar; + covar.resize(3); + covar.clear(); + // Units are km**2 + covar(0,0) = .0001; + covar(1,1) = .0025; + covar(2,2) = .0004; + + spRecKm.SetRectangular(Displacement(-424.024048, Displacement::Meters), + Displacement(734.4311949, Displacement::Meters), + Displacement(529.919264, Displacement::Meters)); + spRecKm.SetMatrix(SurfacePoint::Rectangular, covar); + + lat = spRecKm.GetLatitude().degrees(); + lon = spRecKm.GetLongitude().degrees(); + radius = spRecKm.GetLocalRadius().meters(); + latSig = spRecKm.GetLatSigma().degrees(); + lonSig = spRecKm.GetLonSigma().degrees(); + radSig = spRecKm.GetLocalRadiusSigma().meters(); + symmetric_matrix covarSphKm(3); + covarSphKm.clear(); + covarSphKm = spRecKm.GetSphericalMatrix(SurfacePoint::Kilometers); + + cout << setprecision(9); + cout << " Output spherical..." << endl; + cout << " lat = " << lat << " degrees, lon = " << lon << + " degrees, radius = " << radius << " meters" << endl; + cout << " lat = " << spRecKm.GetLatitude().radians() << + " radians, lon = " << spRecKm.GetLongitude().radians() + << " radians, radius = " << spRecKm.GetLocalRadius().meters() << + " meters" << endl; + cout << " latitude sigma=" << spRecKm.GetLatSigma().radians() << + " radians, longitude sigma=" << spRecKm.GetLonSigma().radians() + << " radians, radius sigma=" << spRecKm.GetLocalRadiusSigma().meters() + << " m" << endl; + + cout << " spherical covariance matrix = " << covarSphKm(0,0) << " " << + covarSphKm(0,1) << " " << covarSphKm(0,2) << endl; + cout << " " << covarSphKm(1,0) << " " << + covarSphKm(1,1) << " " << covarSphKm(1,2) << endl; + cout << " " << covarSphKm(2,0) << " " << + covarSphKm(2,1) << " " << covarSphKm(2,2) << endl; + cout << " Input rectangular sigmas = " << spRecKm.GetXSigma().kilometers() + << "/" << spRecKm.GetYSigma().kilometers() << "/" + << spRecKm.GetZSigma().kilometers() << std::endl; + + cout << endl; + cout << " 6b-Testing spherical set of point and variance/covariance matrix (in km^2)..." + << endl; + // Usage note: In order to get accurate results, the full correlation matrix should be + // used as opposed to only setting the diagonal elements with the sigmas. + cout << " with lat=" << lat << " degrees, lon=" << lon << " degrees, radius=" + << radius << " m" << endl; + cout << " latitude sigma=" << latSig << " deg, longitude sigma=" << lonSig + << " deg, radiusSig=" << radSig << " m" << endl; + Isis::SurfacePoint spSphereKm; + spSphereKm.SetSpherical(Latitude(lat, Angle::Degrees), + Longitude(lon, Angle::Degrees), + Distance(radius, Distance::Meters)); + spSphereKm.SetMatrix(SurfacePoint::Latitudinal, covarSphKm); + symmetric_matrix covarRecKm(3); + covarRecKm.clear(); + covarRecKm = spSphereKm.GetRectangularMatrix(SurfacePoint::Kilometers); + + if(fabs(covarRecKm(0,1)) < 1E-12) covarRecKm(0,1) = 0.0; + if(fabs(covarRecKm(0,2)) < 1E-12) covarRecKm(0,2) = 0.0; + if(fabs(covarRecKm(1,0)) < 1E-12) covarRecKm(1,0) = 0.0; + if(fabs(covarRecKm(1,2)) < 1E-12) covarRecKm(1,2) = 0.0; + if(fabs(covarRecKm(2,0)) < 1E-12) covarRecKm(2,0) = 0.0; + if(fabs(covarRecKm(2,2)) < 1E-12) covarRecKm(2,2) = 0.0; + + cout << " Output rectangular..." << endl; + cout << " x=" << spSphereKm.GetX().meters() + << " m, y=" << spSphereKm.GetY().meters() + << " m, z=" << spSphereKm.GetZ().meters() << " m" << endl; + cout << " X sigma=" << spSphereKm.GetXSigma().meters() << " m, Y sigma=" + << spSphereKm.GetYSigma().meters() << " m, Z sigma=" << + spSphereKm.GetZSigma().meters() << " m" << endl; + cout << " rectangular covariance matrix = " + << setw(10) << covarRecKm(0,0) << setw(10) << covarRecKm(0,1) + << setw(10) << covarRecKm(0,2) << endl; + cout << " " + << setw(10) << covarRecKm(1,0) << setw(10) << covarRecKm(1,1) + << setw(10) << covarRecKm(1,2) << endl; + cout << " " + << setw(10) << covarRecKm(2,0) << setw(10) << covarRecKm(2,1) + << setw(10) << covarRecKm(2,2) << endl << endl; + } catch(Isis::IException &e) { e.print(); } + // Test new code added to support solving and outputting control points in body-fixed + // x/y/z (RECTANGULAR) + + // Set a point for testing - Use coordinate data from test 1 + Isis::SurfacePoint spRec1; + spRec1.SetRectangular(Displacement(-424.024048, Displacement::Meters), + Displacement(734.4311949, Displacement::Meters), + Displacement(529.919264, Displacement::Meters)); + + cout << "Testing error conditions in GetCoord, GetSigma, GetWeight, LatToDouble, " + << endl << "LonToDouble, GetSigmaDistance, DistanceToDouble, and DisplacementToDouble..." + << endl << endl; + + try { + // Test DisplacementToDouble error conditions. (DistanceToDouble, LatToDouble, and LonToDouble) + cout << " ...Test Rectangular GetCoord with incorrect unit Degrees" << endl; + double value = spRec1.GetCoord(SurfacePoint::Rectangular, SurfacePoint::One, + SurfacePoint::Degrees); + cout << "X-degrees = " << value << endl; + } + catch(Isis::IException &e) { + e.print(); + } + + try { + // Test DisplacementToDouble error conditions. (DistanceToDouble, LatToDouble, and LonToDouble) + cout << " ...Test Rectangular GetCoord with incorrect unit Radians" << endl; + double value = spRec1.GetCoord(SurfacePoint::Rectangular, SurfacePoint::One, + SurfacePoint::Radians); + cout << "X-radians = " << value << endl; + } + catch(Isis::IException &e) { + e.print(); + } + + try { + // Test DisplacementToDouble error conditions. (DistanceToDouble, LatToDouble, and LonToDouble) + cout << " ...Test Rectangular GetCoord with incorrect unit Degrees" << endl; + double value = spRec1.GetCoord(SurfacePoint::Latitudinal, SurfacePoint::Three, + SurfacePoint::Degrees); + cout << "Local Radius-degrees = " << value << endl; + } + catch(Isis::IException &e) { + e.print(); + } + + try { + // Test DisplacementToDouble error conditions. (DistanceToDouble, LatToDouble, and LonToDouble) + cout << " ...Test Latitudinal GetCoord with incorrect unit Radians for local radius" << endl; + double value = spRec1.GetCoord(SurfacePoint::Latitudinal, SurfacePoint::Three, + SurfacePoint::Radians); + cout << "Local Radius-radians = " << value << endl; + } + catch(Isis::IException &e) { + e.print(); + } + + try { + // Test DisplacementToDouble error conditions. (DistanceToDouble, LatToDouble, and LonToDouble) + cout << " ...Test Latitudinal GetCoord with incorrect unit Kilometers for latitude" << endl; + double value = spRec1.GetCoord(SurfacePoint::Latitudinal, SurfacePoint::One, + SurfacePoint::Kilometers); + cout << "Latitude-kilometers = " << value << endl; + } + catch(Isis::IException &e) { + e.print(); + } + + try { + // Test DisplacementToDouble error conditions. (DistanceToDouble, LatToDouble, and LonToDouble) + cout << " ...Test Latitudinal GetCoord with incorrect unit Meters for longitude" << endl; + double value = spRec1.GetCoord(SurfacePoint::Latitudinal, SurfacePoint::Two, + SurfacePoint::Kilometers); + cout << "Longitude-meters = " << value << endl; + } + catch(Isis::IException &e) { + e.print(); + } + + try { + // Test point coordinates only set. Try GetWeight. Set sigmas. Try GetWeight. + // Try GetWeight and GetCoord for all possibilities + cout << endl; + cout << "Test error statements: case where weights are requested after only coordinates " + << "have been set..." << endl; + double value = spRec1.GetWeight(SurfacePoint::Rectangular, SurfacePoint::One); + cout << "X sigma-degrees = " << value << endl; + } + catch(Isis::IException &e) { + e.print(); + } + + try { + // Test SetSphericalSigmasDistance error condition + cout << endl; + cout << "Test error statements: case of invalid SurfacePoint in" + << " SetSphericalSigmasDistance " << endl; + SurfacePoint sp; + sp.SetSphericalSigmasDistance(Distance(3.,Distance::Meters), + Distance(3.,Distance::Meters),Distance(3.,Distance::Meters)); + } + catch(Isis::IException &e) { + e.print(); + } + + try { + // Test GetWeight after point coordinates and sigmas have been set. Try GetWeight. Set body + // radii. Try GetWeight, GetSigma and GetCoord for all possibilities. + cout << endl; + cout << "...Testing GetCoord, GetSigma, and GetWeight... " << endl << endl; + spRec1.SetRectangularSigmas(Distance(10.,Distance::Meters), + Distance(50., Distance::Meters), + Distance(20., Distance::Meters)); + + cout << "Rectangular Coordinates kilometers: " << "X= "; + cout << spRec1.GetCoord(SurfacePoint::Rectangular, SurfacePoint::One, + SurfacePoint::Kilometers); + cout << " Y = "; + cout << spRec1.GetCoord(SurfacePoint::Rectangular, SurfacePoint::Two, + SurfacePoint::Kilometers); + cout << " Z = "; + cout << spRec1.GetCoord(SurfacePoint::Rectangular, SurfacePoint::Three, + SurfacePoint::Kilometers); + cout << endl; + + cout << "Rectangular Coordinates meters: " << "X= "; + cout << spRec1.GetCoord(SurfacePoint::Rectangular, SurfacePoint::One, SurfacePoint::Meters); + cout << " Y = "; + cout << spRec1.GetCoord(SurfacePoint::Rectangular, SurfacePoint::Two, SurfacePoint::Meters); + cout << " Z = "; + cout << spRec1.GetCoord(SurfacePoint::Rectangular, SurfacePoint::Three, SurfacePoint::Meters); + cout << endl; + + cout << "Rectangular sigmas kilometers: " << "X= "; + cout << spRec1.GetSigma(SurfacePoint::Rectangular, SurfacePoint::One, + SurfacePoint::Kilometers); + cout << " Y = "; + cout << spRec1.GetSigma(SurfacePoint::Rectangular, SurfacePoint::Two, + SurfacePoint::Kilometers); + cout << " Z = "; + cout << spRec1.GetSigma(SurfacePoint::Rectangular, SurfacePoint::Three, + SurfacePoint::Kilometers); + cout << endl; + + cout << "Using GetSigmaDistance, Rectangular sigmas kilometers: " << "X= "; + cout << spRec1.GetSigmaDistance(SurfacePoint::Rectangular, SurfacePoint::One) + .kilometers(); + cout << " Y = "; + cout << spRec1.GetSigmaDistance(SurfacePoint::Rectangular, SurfacePoint::Two) + .kilometers(); + cout << " Z = "; + cout << spRec1.GetSigmaDistance(SurfacePoint::Rectangular, SurfacePoint::Three) + .kilometers(); + cout << endl; + + cout << "Rectangular sigmas meters: " << "X= "; + cout << spRec1.GetSigma(SurfacePoint::Rectangular, SurfacePoint::One, SurfacePoint::Meters); + cout << " Y = "; + cout << spRec1.GetSigma(SurfacePoint::Rectangular, SurfacePoint::Two, SurfacePoint::Meters); + cout << " Z = "; + cout << spRec1.GetSigma(SurfacePoint::Rectangular, SurfacePoint::Three, SurfacePoint::Meters); + cout << endl; + + cout << "Using GetSigmaDistance, Rectangular sigmas meters: " << "X= "; + cout << spRec1.GetSigmaDistance(SurfacePoint::Rectangular, SurfacePoint::One).meters(); + cout << " Y = "; + cout << spRec1.GetSigmaDistance(SurfacePoint::Rectangular, SurfacePoint::Two).meters(); + cout << " Z = "; + cout << spRec1.GetSigmaDistance(SurfacePoint::Rectangular, SurfacePoint::Three).meters(); + cout << endl; + + cout << "Rectangular Weights kilometers: " << "X = "; + cout << spRec1.GetWeight(SurfacePoint::Rectangular, SurfacePoint::One) << " Y = " + << spRec1.GetWeight(SurfacePoint::Rectangular, SurfacePoint::Two) << " Z = " + << spRec1.GetWeight(SurfacePoint::Rectangular, SurfacePoint::Three) << endl; + + cout << "Latitudinal Coordinates radians: " << "Latitude= "; + cout << spRec1.GetCoord(SurfacePoint::Latitudinal, SurfacePoint::One, SurfacePoint::Radians); + cout << " Longitude = "; + cout << spRec1.GetCoord(SurfacePoint::Latitudinal, SurfacePoint::Two, SurfacePoint::Radians); + cout << " Local Radius = "; + cout << spRec1.GetCoord(SurfacePoint::Latitudinal, SurfacePoint::Three, + SurfacePoint::Kilometers); + cout << endl; + + cout << "Latitudinal Coordinates degrees: " << "Latitude= "; + cout << spRec1.GetCoord(SurfacePoint::Latitudinal, SurfacePoint::One, SurfacePoint::Degrees); + cout << " Longitude = "; + cout << spRec1.GetCoord(SurfacePoint::Latitudinal, SurfacePoint::Two, SurfacePoint::Degrees); + cout << " Local Radius = "; + cout << spRec1.GetCoord(SurfacePoint::Latitudinal, SurfacePoint::Three, SurfacePoint::Meters); + cout << endl; + + cout << "Latitudinal weight degrees: " << "Latitude= "; + cout << spRec1.GetWeight(SurfacePoint::Latitudinal, SurfacePoint::One); + cout << " Longitude = "; + cout << spRec1.GetWeight(SurfacePoint::Latitudinal, SurfacePoint::Two); + cout << " Local Radius = "; + cout << spRec1.GetWeight(SurfacePoint::Latitudinal, SurfacePoint::Three); + cout << endl << endl; + } + catch(Isis::IException &e) { + e.print(); + } + + // Test stringToCoordType and coordinateTypeToString + QString ctypeStr = "Latitudinal"; + SurfacePoint::CoordinateType ctype = spRec1.stringToCoordinateType(ctypeStr); + cout << "Testing stringToCoordinateType with Latitudinal: coordType = " << ctype << endl; + cout << "Testing coordinateTypeToString with coordType = 0: coordTypeStr = " << + spRec1.coordinateTypeToString(ctype) << endl; + ctypeStr = "RectanGular"; + ctype = spRec1.stringToCoordinateType(ctypeStr); + cout << "Testing stringToCoordinateType with Rectangular: coordType = " << ctype << endl; + cout << "Testing coordinateTypeToString with coordType = 1: coordTypeStr = " << + spRec1.coordinateTypeToString(ctype) << endl; + try { + // Test invalid coordinate type error condition + cout << endl; + cout << "Test invalid coordinate type error condition." << endl; + ctypeStr = "Garbage"; + ctype = spRec1.stringToCoordinateType(ctypeStr); + cout << "Testing stringToCoordinateType with Garbage: coordType = " << ctype << endl; + } + catch(Isis::IException &e) { + e.print(); + } + + cout << endl; cout << "Test computational methods..." << endl; cout << " SphericalDistanceToPoint (i.e. haversine): "; diff --git a/isis/src/base/objs/Target/Target.cpp b/isis/src/base/objs/Target/Target.cpp index 88c6663d38046a3c3a110f161b5de0468c119c12..62ebc1928ac888d0efacd9ea911df6a814c73a8f 100644 --- a/isis/src/base/objs/Target/Target.cpp +++ b/isis/src/base/objs/Target/Target.cpp @@ -196,19 +196,21 @@ namespace Isis { } catch (IException &e) { try { + // Get body code from Isis Naif object if it exists or Naif data pool if (m_spice) { - code = m_spice->getInteger("BODY_FRAME_CODE", 0); + code = m_spice->getInteger("BODY_CODE", 0); return code; } + // getInteger automatically calls Spice::readValue which looks in the NaifKeywords else if (lab.hasObject("NaifKeywords") - && lab.findObject("NaifKeywords").hasKeyword("BODY_FRAME_CODE") ) { - code = int(lab.findObject("NaifKeywords").findKeyword("BODY_FRAME_CODE")); + && lab.findObject("NaifKeywords").hasKeyword("BODY_CODE") ) { + code = int(lab.findObject("NaifKeywords").findKeyword("BODY_CODE")); return code; } else { throw IException(e, IException::Unknown, - "BODY_FRAME_CODE not found for this Target.", + "BODY_CODE not found for this Target.", _FILEINFO_); } } @@ -272,7 +274,7 @@ namespace Isis { } // If radii values are not in the given mapping group, we will get the target from the mapping - // group or cube label and attempt use NAIF routines to find the radii. + // group or cube label and attempt to use NAIF routines to find the radii. QString target = ""; try { if (mapping.hasKeyword("TargetName")) { @@ -313,15 +315,39 @@ namespace Isis { // If all previous attempts fail, look for the radii using the body frame // code in the NaifKeywords object. // Note: We will only look in the given label for the values after SPICELIB - // routines have failed to preserve backwards compatibility (since this + // routines have failed, to preserve backwards compatibility (since this // label check is new). if (cubeLab.hasObject("NaifKeywords")) { PvlObject naifKeywords = cubeLab.findObject("NaifKeywords"); - + + // Try using the target bodycode_RADII keyword in the NaifKeywords PVL object + try { + + SpiceInt bodyCode = 0; + try { + // Try using the target bodycode_RADII keyword in the NaifKeywords PVL object + bodyCode = lookupNaifBodyCode(target); + } + catch (IException &e2) { + throw IException(e, IException::Unknown, e2.what(), _FILEINFO_); + } + QString radiiKeyword = "BODY" + toString(int(bodyCode)) + "_RADII"; - // Try using the value of the BODY_FRAME_CODE keyword in the NaifKeywords PVL object + if (naifKeywords.hasKeyword(radiiKeyword)) { + PvlKeyword radii = naifKeywords.findKeyword(radiiKeyword); + mapping.addKeyword( PvlKeyword("EquatorialRadius", + toString(toDouble(radii[0]) * 1000.0), "meters"), + PvlContainer::Replace); + mapping.addKeyword( PvlKeyword("PolarRadius", + toString(toDouble(radii[2]) * 1000.0), "meters"), + PvlContainer::Replace); + return mapping; + } + } + catch (IException &e) { + // Try using the value of the BODY_FRAME_CODE keyword in the NaifKeywords PVL object if (naifKeywords.hasKeyword("BODY_FRAME_CODE")) { PvlKeyword bodyFrame = naifKeywords.findKeyword("BODY_FRAME_CODE"); @@ -339,40 +365,6 @@ namespace Isis { PvlContainer::Replace); return mapping; } - // Try getting the radii using the BODY_FRAME_CODE with SPICELIB - else { - PvlGroup radiiGroup = Target::radiiGroup(toInt(bodyFrame[0])); - // Now APPEND the EquatorialRadius and PolorRadius - mapping.addKeyword( radiiGroup.findKeyword("EquatorialRadius"), PvlContainer::Replace); - mapping.addKeyword( radiiGroup.findKeyword("PolarRadius"), PvlContainer::Replace); - return mapping; - - - } - } - } - catch (IException &e) { - - // Try using the BODYbodycode_RADII keyword in the NaifKeywords PVL object - SpiceInt bodyCode = 0; - try { - bodyCode = lookupNaifBodyCode(target); - } - catch (IException &e2) { - throw IException(e, IException::Unknown, e2.what(), _FILEINFO_); - } - - QString radiiKeyword = "BODY" + toString(int(bodyCode)) + "_RADII"; - - if (naifKeywords.hasKeyword(radiiKeyword)) { - PvlKeyword radii = naifKeywords.findKeyword(radiiKeyword); - mapping.addKeyword( PvlKeyword("EquatorialRadius", - toString(toDouble(radii[0]) * 1000.0), "meters"), - PvlContainer::Replace); - mapping.addKeyword( PvlKeyword("PolarRadius", - toString(toDouble(radii[2]) * 1000.0), "meters"), - PvlContainer::Replace); - return mapping; } } } @@ -414,9 +406,9 @@ namespace Isis { } else { - SpiceInt bodyFrame = 0; + SpiceInt bodyCode = 0; try { - bodyFrame = lookupNaifBodyCode(target); + bodyCode = lookupNaifBodyCode(target); } catch (IException &e) { QString msg = "Unable to find target radii for given target [" @@ -424,7 +416,7 @@ namespace Isis { throw IException(IException::Io, msg, _FILEINFO_); } - PvlGroup radiiGroup = Target::radiiGroup(int(bodyFrame)); + PvlGroup radiiGroup = Target::radiiGroup(int(bodyCode)); mapping += PvlKeyword("TargetName", target); mapping += radiiGroup.findKeyword("EquatorialRadius"); mapping += radiiGroup.findKeyword("PolarRadius"); @@ -437,7 +429,7 @@ namespace Isis { /** * Convenience method called by the public radii() methods to - * compute the target radii using a body frame code recognized by NAIF. + * compute the target radii using a body code recognized by NAIF. * * The PVL group contains only the EquatorialRadius and PolarRadius * keywords. This group does not contain the Target keyword. @@ -446,7 +438,7 @@ namespace Isis { * * @return PvlGroup containing EquatorialRadius and PolarRadius keywords. */ - PvlGroup Target::radiiGroup(int bodyFrameCode) { + PvlGroup Target::radiiGroup(int bodyCode) { // Load the most recent target attitude and shape kernel for NAIF static bool pckLoaded = false; @@ -465,13 +457,13 @@ namespace Isis { // Get the radii from NAIF SpiceInt n; SpiceDouble radii[3]; - bodvar_c(bodyFrameCode, "RADII", &n, radii); + bodvar_c(bodyCode, "RADII", &n, radii); try { NaifStatus::CheckErrors(); } catch (IException &e) { - QString msg = "Unable to find radii for target code [" + toString(bodyFrameCode) + QString msg = "Unable to find radii for target code [" + toString(bodyCode) + "]. Target code was not found in furnished kernels."; throw IException(e, IException::Unknown, msg, _FILEINFO_); diff --git a/isis/src/base/objs/Target/Target.h b/isis/src/base/objs/Target/Target.h index 7c488937a522054abee386a66c4eb3938fa385d4..1cd41059702552339d0b5817d9fd4f67e6619426 100644 --- a/isis/src/base/objs/Target/Target.h +++ b/isis/src/base/objs/Target/Target.h @@ -62,6 +62,16 @@ namespace Isis { * @history 2017-08-14 Stuart Sides - Added the ability to use a target code and the * NaifKeywords to find the radii. Added so osirisrex and spicelib v66. * References #4947. + * @history 2018-10-02 Debbie A. Cook - Fixed method lookupNaifBodyCode to look + * up the Naif body code instead of the Naif body frame code. We may + * need to add a method to look up the Naif body frame code as well. + * Also moved the try loop attempting to find the radii tagged with the + * Naif body code ahead of the try loop that attempts to find the radii + * tagged with the body frame code in the method radiiGroup. Fixed + * any mention of Naif body frame code that should be Naif body code. + * These are not the same. Naif tags the body radii keyword with the + * Naif body code. The Naif body frame code refers to the orientation + * (SpiceRotation) of the body. References #4649 and #501. */ class Target { diff --git a/isis/src/base/objs/Target/Target.truth b/isis/src/base/objs/Target/Target.truth index 950cba674a0bd70be34bbaf7c9ed5e026308dd0f..d824e2aca4a39d8bcf6bf317f02de9c534bca9e7 100644 --- a/isis/src/base/objs/Target/Target.truth +++ b/isis/src/base/objs/Target/Target.truth @@ -27,7 +27,7 @@ Unit test for Isis::Target Testing unknown target ... **ERROR** Unable to look up NAIF body code for this Target. **I/O ERROR** Could not convert Target [Mard] to NAIF body code. -**ERROR** BODY_FRAME_CODE not found for this Target. +**ERROR** BODY_CODE not found for this Target. **I/O ERROR** Could not convert Target [Mard] to NAIF body code. @@ -191,9 +191,8 @@ End_Group RETURNS: -**ERROR** **I/O ERROR** Could not convert Target [Chewbaca] to NAIF body code. -**ERROR** Unable to find radii for target code [2101955]. Target code was not found in furnished kernels. -**ERROR** An unknown NAIF error has been encountered. The short explanation provided by NAIF is [SPICE(KERNELVARNOTFOUND)]. The Naif error is [The variable BODY2101955_RADII could not be found in the kernel pool.]. +**ERROR** Unable to find Equatorial and Polar radii for target [Chewbaca]. +**I/O ERROR** Unable to find target radii for given target [Chewbaca]. ------------------------------- ------------------------------- diff --git a/isis/src/cassini/apps/ciss2isis/ciss2isis.cpp b/isis/src/cassini/apps/ciss2isis/ciss2isis.cpp index ab81f852563e605967f19e84c1ea3bc706f92035..2ce069e018b31a5a249722918ddc67e3d338115d 100644 --- a/isis/src/cassini/apps/ciss2isis/ciss2isis.cpp +++ b/isis/src/cassini/apps/ciss2isis/ciss2isis.cpp @@ -229,12 +229,15 @@ void CreateStretchPairs() { return; } -// The input buffer has a raw 16 bit buffer but the values are still 0 to 255. -// We know that 255 (stretched to 4095 if Table converted) is saturated. -// Sky pixels could have valid DN of 0, but missing pixels are also saved as 0, -// so it is impossible to distinguish between them. -// This method is used by ConvertLinePrefixPixels() and IsisMain() for ProcessByLine p2. -// author Jeannie Walldren 2008-08-21 +/** +* The input buffer has a raw 16 bit buffer but the values are still 0 to 255. +* We know that 255 (stretched to 4095 if Table converted) is saturated. +* Sky pixels could have valid DN of 0, but missing pixels are also saved as 0, +* so it is impossible to distinguish between them. +* This method is used by ConvertLinePrefixPixels() and IsisMain() for ProcessByLine p2. +* author Jeannie Walldren 2008-08-21 +* +*/ void FixDns(Buffer &buf) { for(int i = 0; i < buf.size(); i++) { // zeros and negatives are valid DN values, according to scientists, @@ -452,4 +455,3 @@ double ComputeOverclockAvg(vector pixel) { // IDL cisscal application files: cassimg_subtractdark.pro and linetime.pro // -Jeannie Walldren 08/06/2008 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - diff --git a/isis/src/cassini/apps/ciss2isis/ciss2isis.xml b/isis/src/cassini/apps/ciss2isis/ciss2isis.xml index f2714b5bce1ae48867cf2e873359c92cc7a96805..5d77ef85ec484681c4df3e6192d2fbffb77b0c86 100644 --- a/isis/src/cassini/apps/ciss2isis/ciss2isis.xml +++ b/isis/src/cassini/apps/ciss2isis/ciss2isis.xml @@ -3,16 +3,16 @@ - Import a PDS Cassini ISS image file into Isis + Import a PDS Cassini ISS image file into Isis This program will import a PDS Cassini ISS image file into an Isis cube. Some Cassini files available from PDS contain VICAR labels THIS PROGRAM ONLY ACCEPTS PDS LABELS. You must specify an - input file which contains PDS labels. Note: Scientists - indicate that zeros may be valid DN values for sky areas of CISS images, - but missing pixels are also assigned a value of zero and there is no known + input file which contains PDS labels. Note: Scientists + indicate that zeros may be valid DN values for sky areas of CISS images, + but missing pixels are also assigned a value of zero and there is no known way to distinguish them. Since the chance of a valid zero DN is so slight, ciss2isis will replace all zeros with Isis::Null. @@ -35,24 +35,24 @@ Checks if input file is rdr. - Modified application to - save off binary file header and compute read out order, to save off line - prefix data of overclocked pixels with the appropriate overclock average - into a table, and to convert compressed 8bit images to 16bit using a - look-up table. Added keywords, with units where appropriate, to labels. + Modified application to + save off binary file header and compute read out order, to save off line + prefix data of overclocked pixels with the appropriate overclock average + into a table, and to convert compressed 8bit images to 16bit using a + look-up table. Added keywords, with units where appropriate, to labels. - Modified to - allow import of images with BandBin filter combinations not found or - commented out in the translation *.def files. Previously, this - circumstance stopped the program and threw an exception. Application now + Modified to + allow import of images with BandBin filter combinations not found or + commented out in the translation *.def files. Previously, this + circumstance stopped the program and threw an exception. Application now outputs a warning to the log but still creates the cube. Modified FixDns method and updated documentation. - Modified to convert BiasStripMean value back to 12-bit using look up table - for images with DataConversionType of Table. Updated documentation in + Modified to convert BiasStripMean value back to 12-bit using look up table + for images with DataConversionType of Table. Updated documentation in ciss2isis.cpp @@ -70,13 +70,13 @@ - + Insert hyperlinks to section Related Objects and Documents, subsection Documents. - Since zeros may be valid DNs and missing pixels are set to zero, - investigate whether there is a way to distinguish the two. If so, update + Since zeros may be valid DNs and missing pixels are set to zero, + investigate whether there is a way to distinguish the two. If so, update FixDns method in cisscal.cpp. @@ -90,8 +90,8 @@ Cassini ISS Software - Interface Specification (SIS) -- - https://cel.jpl.nasa.gov/cedr/home/mcdl.html + Interface Specification (SIS) -- + https://cel.jpl.nasa.gov/cedr/home/mcdl.html @@ -148,7 +148,7 @@ Using ciss2isis - The use of ciss2isis to ingest PDS images and output Isis3 cubes. + The use of ciss2isis to ingest PDS images and output Isis3 cubes. @@ -156,10 +156,10 @@ to= N1472853667_1.cub - This example shows the use of ciss2isis create an Isis3 cube from a PDS image. + This example shows the use of ciss2isis create an Isis3 cube from a PDS image. - + @@ -196,7 +196,7 @@ TO - + diff --git a/isis/src/control/apps/deltack/deltack.cpp b/isis/src/control/apps/deltack/deltack.cpp index 529c84a9a53adf2a90692890cec9820a5bf26868..1b78cb116a420d3a6c33ef4bdae30643b12aafac 100644 --- a/isis/src/control/apps/deltack/deltack.cpp +++ b/isis/src/control/apps/deltack/deltack.cpp @@ -354,7 +354,8 @@ BundleSettingsQsp bundleSettings() { // longitude sigma = 1000.0 // radius sigma = Null since we are not solving for radius // outlier rejection = false - settings->setSolveOptions(false, false, false, false, 1000.0, 1000.0, Isis::Null); + settings->setSolveOptions(false, false, false, false, SurfacePoint::Latitudinal, + SurfacePoint::Latitudinal, 1000.0, 1000.0, Isis::Null); settings->setOutlierRejection(false); // =========================================================================================// diff --git a/isis/src/control/apps/jigsaw/jigsaw.cpp b/isis/src/control/apps/jigsaw/jigsaw.cpp index daf0f46865a90dbff1cd075903daf5b540d1befc..6d0d6320e9fcc37ab28dce05939f8811ca37466d 100644 --- a/isis/src/control/apps/jigsaw/jigsaw.cpp +++ b/isis/src/control/apps/jigsaw/jigsaw.cpp @@ -166,26 +166,49 @@ BundleSettingsQsp bundleSettings(UserInterface &ui) { settings->setValidateNetwork(true); // solve options - double latitudeSigma = Isis::Null; - double longitudeSigma = Isis::Null; - double radiusSigma = Isis::Null; + QString coordTypeBundleStr = ui.GetString("CONTROL_POINT_COORDINATE_TYPE_BUNDLE"); + QString coordTypeReportsStr = ui.GetString("CONTROL_POINT_COORDINATE_TYPE_REPORTS"); + SurfacePoint::CoordinateType ctypeBundle = SurfacePoint::Latitudinal; + SurfacePoint::CoordinateType ctypeReports = SurfacePoint::Latitudinal; + + if (coordTypeBundleStr == "RECTANGULAR") { + ctypeBundle = SurfacePoint::Rectangular; + } + + if (coordTypeReportsStr == "RECTANGULAR") { + ctypeReports = SurfacePoint::Rectangular; + } + + double coord1Sigma = Isis::Null; + double coord2Sigma = Isis::Null; + double coord3Sigma = Isis::Null; if (ui.WasEntered("POINT_LATITUDE_SIGMA")) { - latitudeSigma = ui.GetDouble("POINT_LATITUDE_SIGMA"); + coord1Sigma = ui.GetDouble("POINT_LATITUDE_SIGMA"); } if (ui.WasEntered("POINT_LONGITUDE_SIGMA")) { - longitudeSigma = ui.GetDouble("POINT_LONGITUDE_SIGMA"); + coord2Sigma = ui.GetDouble("POINT_LONGITUDE_SIGMA"); } if (ui.WasEntered("POINT_RADIUS_SIGMA")) { - radiusSigma = ui.GetDouble("POINT_RADIUS_SIGMA"); + coord3Sigma = ui.GetDouble("POINT_RADIUS_SIGMA"); + } + if (ui.WasEntered("POINT_X_SIGMA")) { + coord1Sigma = ui.GetDouble("POINT_X_SIGMA"); + } + if (ui.WasEntered("POINT_Y_SIGMA")) { + coord2Sigma = ui.GetDouble("POINT_Y_SIGMA"); + } + if (ui.WasEntered("POINT_Z_SIGMA")) { + coord3Sigma = ui.GetDouble("POINT_Z_SIGMA"); } settings->setSolveOptions(ui.GetBoolean("OBSERVATIONS"), ui.GetBoolean("UPDATE"), ui.GetBoolean("ERRORPROPAGATION"), ui.GetBoolean("RADIUS"), - latitudeSigma, - longitudeSigma, - radiusSigma); + ctypeBundle, ctypeReports, + coord1Sigma, + coord2Sigma, + coord3Sigma); // Don't create the inverse correlation matrix file settings->setCreateInverseMatrix(false); diff --git a/isis/src/control/apps/jigsaw/jigsaw.xml b/isis/src/control/apps/jigsaw/jigsaw.xml index 460aaad7a001949cea65154fcc46aa906ba45c45..2b54de33be477275e91ecafef403125bd9fc12e6 100644 --- a/isis/src/control/apps/jigsaw/jigsaw.xml +++ b/isis/src/control/apps/jigsaw/jigsaw.xml @@ -257,6 +257,22 @@ BundleSolutionInfo object. Am also deleting this pointer because jigsaw.cpp takes ownership from BundleAdjust. + + (BundleXYZ modified on 2017-09-11) Added options for outputting + and/or solving for body-fixed x/y/z instead of lat/lon/radius. + References #501. + + + (BundleXYZ modified on 2017-09-17) Fixed a problem in the + xml that was causing the input parameters to be omitted from + the history. References #501. + + + (BundleXYZ modified on 2018-03-18) Fixed a problem in the xml + that excluded entry of values for latitudinal point sigmas when the + coordinate type for reports was set to Rectangular and vice versa. + References #501. + @@ -1023,6 +1039,77 @@ + + + string + Coordinate type to use for bundling and outputting control points + + LATITUDINAL + + + This parameter indicates which coordinate type will be used to present + the control points in the bundle adjustment and bundle output. + + + + + + + + + string + Coordinate type to use for bundling and outputting control points + + LATITUDINAL + + + This parameter indicates which coordinate type will be used to present + the control points in the bundle adjustment and bundle output. + + + + + + + + + Global latitude uncertainty for all points (meters) @@ -1065,6 +1152,42 @@ + + Global body-fixed X uncertainty for all points (meters) + + + This optional value will be used as the global + uncertainty for all points. Units are meters. + + double + none + 0 + + + + Global body-fixed X uncertainty for all points (meters) + + + This optional value will be used as the global + uncertainty for all points. Units are meters. + + double + none + 0 + + + + Global body-fixed X uncertainty for all points (meters) + + + This optional value will be used as the global + uncertainty for all points. Units are meters. + + double + none + 0 + + Global uncertainty for spacecraft coordinates (meters) diff --git a/isis/src/control/apps/jigsaw/tsts/bundleXYZ/Makefile b/isis/src/control/apps/jigsaw/tsts/bundleXYZ/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..c8821dcc23fc92da69bfa8a401a4ae4b41423bdc --- /dev/null +++ b/isis/src/control/apps/jigsaw/tsts/bundleXYZ/Makefile @@ -0,0 +1,219 @@ +APPNAME = jigsaw +# These tests exercise the bundle adjustment of Apollo images using the bundleXYZ options +# These tests should probably be replaced with Bennu data or other more appropriate data. +# Solving for position, angles (with twist), and radius with error propagation. +# +# 2018-10-12 Debbie A. Cook - original test +# 2018-10-22 Jesse Mapel - Added DIFF file for control network. Reduced number of +# decimals in CSVs. + +# The "cat bundleout.txt" command in these tests uses sed to do the following (in order): +# 1. remove cube filename paths +# 2. remove net filename paths +# 3. remove digits beyond the fifth decimal place of decimal numbers +# TODO Change truncation to at least 7th decimal place for free tests +# 4. remove date and time + +include $(ISISROOT)/make/isismake.tsts + +commands: +# test rect bundle with lat output some points constrained + $(LS) -1 $(INPUT)/*.cub > $(OUTPUT)/cube.lis; + $(APPNAME) fromlist=$(OUTPUT)/cube.lis \ + cnet=$(INPUT)/Ames_7-ImageLSTest_USGS_combined.net \ + onet=$(OUTPUT)/rect-latConstrained_out.net \ + radius=yes \ + errorpropagation=yes \ + spsolve=position \ + spacecraft_position_sigma=1000.0 \ + camera_angles_sigma=2. \ + control_point_coordinate_type_bundle=RECT \ + control_point_coordinate_type_reports=LAT \ + file_prefix=$(OUTPUT)/ > /dev/null; + $(CAT) $(OUTPUT)/bundleout.txt | grep -v "Run Time:" | grep -v "Elapsed Time:" \ + | perl -pe 's/(^|,|: )([^,:]+\/)([^,\/:]*\.)(net|cub)/\1\3\4/g' 2>/dev/null \ + | $(SED) 's/\([0-9][0-9]*\.[0-9][0-9][0-9][0-9]\)\([0-9][0-9]*\)/\1/g' \ + | $(SED) s/`date +%Y-%m-%dT`\[0-2\]\[0-9\]:\[0-5\]\[0-9\]:\[0-5\]\[0-9\]/date/ \ + > $(OUTPUT)/rect-latConstrained_bundleout.txt; + $(CAT) $(OUTPUT)/residuals.csv \ + | perl -pe 's/(^|,|: )([^,:]+\/)([^,\/:]*\.)(net|cub)/\1\3\4/g' 2>/dev/null \ + | $(SED) 's/\([0-9][0-9]*\.[0-9][0-9][0-9][0-9][0-9][0-9]\)\([0-9][0-9]*\)/\1/g' \ + > $(OUTPUT)/rect-latConstrained_residuals.csv; + $(CAT) $(OUTPUT)/bundleout_images.csv \ + | perl -pe 's/(^|,|: )([^,:]+\/)([^,\/:]*\.)(net|cub)/\1\3\4/g' 2>/dev/null \ + | $(SED) 's/\([0-9][0-9]*\.[0-9][0-9][0-9][0-9][0-9][0-9]\)\([0-9][0-9]*\)/\1/g' \ + > $(OUTPUT)/rect-latConstrained_bundleout_images.csv; + $(RM) $(OUTPUT)/bundleout_images.csv > /dev/null; + $(MV) $(OUTPUT)/bundleout_points.csv $(OUTPUT)/rect-latConstrained_bundleout_points.csv > /dev/null; + $(RM) $(OUTPUT)/bundleout.txt print.prt > /dev/null; + $(RM) $(OUTPUT)/residuals.csv > /dev/null; + +# test rect bundle and rect output with a free network (all points free) - (sigma 0 should match lat bundle with rect output + $(APPNAME) fromlist=$(OUTPUT)/cube.lis \ + cnet=$(INPUT)/Ames_free.net \ + onet=$(OUTPUT)/rectFree_out.net \ + radius=yes \ + errorpropagation=yes \ + control_point_coordinate_type_bundle=RECT \ + control_point_coordinate_type_reports=RECT \ + file_prefix=$(OUTPUT)/ > /dev/null; + $(CAT) $(OUTPUT)/bundleout.txt | grep -v "Run Time:" | grep -v "Elapsed Time:" \ + | perl -pe 's/(^|,|: )([^,:]+\/)([^,\/:]*\.)(net|cub)/\1\3\4/g' 2>/dev/null \ + | $(SED) 's/\([0-9][0-9]*\.[0-9][0-9][0-9][0-9]\)\([0-9][0-9]*\)/\1/g' \ + | $(SED) s/`date +%Y-%m-%dT`\[0-2\]\[0-9\]:\[0-5\]\[0-9\]:\[0-5\]\[0-9\]/date/ \ + > $(OUTPUT)/rectFree_bundleout.txt; + $(CAT) $(OUTPUT)/residuals.csv \ + | perl -pe 's/(^|,|: )([^,:]+\/)([^,\/:]*\.)(net|cub)/\1\3\4/g' 2>/dev/null \ + | $(SED) 's/\([0-9][0-9]*\.[0-9][0-9][0-9][0-9][0-9][0-9]\)\([0-9][0-9]*\)/\1/g' \ + > $(OUTPUT)/rectFree_residuals.csv; + $(CAT) $(OUTPUT)/bundleout_images.csv \ + | perl -pe 's/(^|,|: )([^,:]+\/)([^,\/:]*\.)(net|cub)/\1\3\4/g' 2>/dev/null \ + | $(SED) 's/\([0-9][0-9]*\.[0-9][0-9][0-9][0-9][0-9][0-9]\)\([0-9][0-9]*\)/\1/g' \ + > $(OUTPUT)/rectFree_bundleout_images.csv; + $(RM) $(OUTPUT)/bundleout_images.csv > /dev/null; + $(MV) $(OUTPUT)/bundleout_points.csv $(OUTPUT)/rectFree_bundleout_points.csv > /dev/null; + $(RM) $(OUTPUT)/bundleout.txt print.prt > /dev/null; + $(RM) $(OUTPUT)/residuals.csv > /dev/null; + +# test lat bundle and rect output with a free network (all points free) - (sigma 0 should match rect bundle with rect outpu + $(APPNAME) fromlist=$(OUTPUT)/cube.lis \ + cnet=$(INPUT)/Ames_free.net \ + onet=$(OUTPUT)/lat-rectFree_out.net \ + radius=yes \ + errorpropagation=yes \ + control_point_coordinate_type_bundle=LAT \ + control_point_coordinate_type_reports=RECT \ + file_prefix=$(OUTPUT)/ > /dev/null; + $(CAT) $(OUTPUT)/bundleout.txt | grep -v "Run Time:" | grep -v "Elapsed Time:" \ + | perl -pe 's/(^|,|: )([^,:]+\/)([^,\/:]*\.)(net|cub)/\1\3\4/g' 2>/dev/null \ + | $(SED) 's/\([0-9][0-9]*\.[0-9][0-9][0-9][0-9]\)\([0-9][0-9]*\)/\1/g' \ + | $(SED) s/`date +%Y-%m-%dT`\[0-2\]\[0-9\]:\[0-5\]\[0-9\]:\[0-5\]\[0-9\]/date/ \ + > $(OUTPUT)/lat-rectFree_bundleout.txt; + $(CAT) $(OUTPUT)/residuals.csv \ + | perl -pe 's/(^|,|: )([^,:]+\/)([^,\/:]*\.)(net|cub)/\1\3\4/g' 2>/dev/null \ + | $(SED) 's/\([0-9][0-9]*\.[0-9][0-9][0-9][0-9][0-9][0-9]\)\([0-9][0-9]*\)/\1/g' \ + > $(OUTPUT)/lat-rectFree_residuals.csv; + $(CAT) $(OUTPUT)/bundleout_images.csv \ + | perl -pe 's/(^|,|: )([^,:]+\/)([^,\/:]*\.)(net|cub)/\1\3\4/g' 2>/dev/null \ + | $(SED) 's/\([0-9][0-9]*\.[0-9][0-9][0-9][0-9][0-9][0-9]\)\([0-9][0-9]*\)/\1/g' \ + > $(OUTPUT)/lat-rectFree_bundleout_images.csv; + $(RM) $(OUTPUT)/bundleout_images.csv > /dev/null; + $(MV) $(OUTPUT)/bundleout_points.csv $(OUTPUT)/lat-rectFree_bundleout_points.csv > /dev/null; + $(RM) $(OUTPUT)/bundleout.txt print.prt > /dev/null; + $(RM) $(OUTPUT)/residuals.csv > /dev/null; + +# test lat bundle and rect output with some constrained points + $(APPNAME) fromlist=$(OUTPUT)/cube.lis \ + cnet=$(INPUT)/Ames_7-ImageLSTest_USGS_combined.net \ + onet=$(OUTPUT)/lat-rectConstrained_out.net \ + radius=yes \ + errorpropagation=yes \ + spsolve=position \ + spacecraft_position_sigma=1000.0 \ + camera_angles_sigma=2. \ + control_point_coordinate_type_bundle=LAT \ + control_point_coordinate_type_reports=RECT \ + file_prefix=$(OUTPUT)/ > /dev/null; + $(CAT) $(OUTPUT)/bundleout.txt | grep -v "Run Time:" | grep -v "Elapsed Time:" \ + | perl -pe 's/(^|,|: )([^,:]+\/)([^,\/:]*\.)(net|cub)/\1\3\4/g' 2>/dev/null \ + | $(SED) 's/\([0-9][0-9]*\.[0-9][0-9][0-9][0-9]\)\([0-9][0-9]*\)/\1/g' \ + | $(SED) s/`date +%Y-%m-%dT`\[0-2\]\[0-9\]:\[0-5\]\[0-9\]:\[0-5\]\[0-9\]/date/ \ + > $(OUTPUT)/lat-rectConstrained_bundleout.txt; + $(CAT) $(OUTPUT)/residuals.csv \ + | perl -pe 's/(^|,|: )([^,:]+\/)([^,\/:]*\.)(net|cub)/\1\3\4/g' 2>/dev/null \ + | $(SED) 's/\([0-9][0-9]*\.[0-9][0-9][0-9][0-9][0-9][0-9]\)\([0-9][0-9]*\)/\1/g' \ + > $(OUTPUT)/lat-rectConstrained_residuals.csv; + $(CAT) $(OUTPUT)/bundleout_images.csv \ + | perl -pe 's/(^|,|: )([^,:]+\/)([^,\/:]*\.)(net|cub)/\1\3\4/g' 2>/dev/null \ + | $(SED) 's/\([0-9][0-9]*\.[0-9][0-9][0-9][0-9][0-9][0-9]\)\([0-9][0-9]*\)/\1/g' \ + > $(OUTPUT)/lat-rectConstrained_bundleout_images.csv; + $(RM) $(OUTPUT)/bundleout_images.csv > /dev/null; + $(MV) $(OUTPUT)/bundleout_points.csv $(OUTPUT)/lat-rectConstrained_bundleout_points.csv > /dev/null; + $(RM) $(OUTPUT)/bundleout.txt print.prt > /dev/null; + $(RM) $(OUTPUT)/residuals.csv > /dev/null; + +# test rect bundle and rect output with some constrained points + $(APPNAME) fromlist=$(OUTPUT)/cube.lis \ + cnet=$(INPUT)/Ames_7-ImageLSTest_USGS_combined.net \ + onet=$(OUTPUT)/rectConstrained_out.net \ + radius=yes \ + errorpropagation=yes \ + spsolve=position \ + spacecraft_position_sigma=1000.0 \ + camera_angles_sigma=2. \ + control_point_coordinate_type_bundle=RECT \ + control_point_coordinate_type_reports=RECT \ + file_prefix=$(OUTPUT)/ > /dev/null; + $(CAT) $(OUTPUT)/bundleout.txt | grep -v "Run Time:" | grep -v "Elapsed Time:" \ + | perl -pe 's/(^|,|: )([^,:]+\/)([^,\/:]*\.)(net|cub)/\1\3\4/g' 2>/dev/null \ + | $(SED) 's/\([0-9][0-9]*\.[0-9][0-9][0-9][0-9]\)\([0-9][0-9]*\)/\1/g' \ + | $(SED) s/`date +%Y-%m-%dT`\[0-2\]\[0-9\]:\[0-5\]\[0-9\]:\[0-5\]\[0-9\]/date/ \ + > $(OUTPUT)/rectConstrained_bundleout.txt; + $(CAT) $(OUTPUT)/residuals.csv \ + | perl -pe 's/(^|,|: )([^,:]+\/)([^,\/:]*\.)(net|cub)/\1\3\4/g' 2>/dev/null \ + | $(SED) 's/\([0-9][0-9]*\.[0-9][0-9][0-9][0-9][0-9][0-9]\)\([0-9][0-9]*\)/\1/g' \ + > $(OUTPUT)/rectConstrained_residuals.csv; + $(CAT) $(OUTPUT)/bundleout_images.csv \ + | perl -pe 's/(^|,|: )([^,:]+\/)([^,\/:]*\.)(net|cub)/\1\3\4/g' 2>/dev/null \ + | $(SED) 's/\([0-9][0-9]*\.[0-9][0-9][0-9][0-9][0-9][0-9]\)\([0-9][0-9]*\)/\1/g' \ + > $(OUTPUT)/rectConstrained_bundleout_images.csv; + $(RM) $(OUTPUT)/bundleout_images.csv > /dev/null; + $(MV) $(OUTPUT)/bundleout_points.csv $(OUTPUT)/rectConstrained_bundleout_points.csv > /dev/null; + $(RM) $(OUTPUT)/bundleout.txt print.prt > /dev/null; + $(RM) $(OUTPUT)/residuals.csv > /dev/null; + +# test rect bundle and lat output with a free network (all points free) - (sigma 0 should match lat bundle with lat output + $(APPNAME) fromlist=$(OUTPUT)/cube.lis \ + cnet=$(INPUT)/Ames_free.net \ + onet=$(OUTPUT)/rect-latFree_out.net \ + radius=yes \ + errorpropagation=yes \ + control_point_coordinate_type_bundle=RECT \ + control_point_coordinate_type_reports=LAT \ + file_prefix=$(OUTPUT)/ > /dev/null; + $(CAT) $(OUTPUT)/bundleout.txt | grep -v "Run Time:" | grep -v "Elapsed Time:" \ + | perl -pe 's/(^|,|: )([^,:]+\/)([^,\/:]*\.)(net|cub)/\1\3\4/g' 2>/dev/null \ + | $(SED) 's/\([0-9][0-9]*\.[0-9][0-9][0-9][0-9]\)\([0-9][0-9]*\)/\1/g' \ + | $(SED) s/`date +%Y-%m-%dT`\[0-2\]\[0-9\]:\[0-5\]\[0-9\]:\[0-5\]\[0-9\]/date/ \ + > $(OUTPUT)/rect-latFree_bundleout.txt; + $(CAT) $(OUTPUT)/residuals.csv \ + | perl -pe 's/(^|,|: )([^,:]+\/)([^,\/:]*\.)(net|cub)/\1\3\4/g' 2>/dev/null \ + | $(SED) 's/\([0-9][0-9]*\.[0-9][0-9][0-9][0-9][0-9][0-9]\)\([0-9][0-9]*\)/\1/g' \ + > $(OUTPUT)/rect-latFree_residuals.csv; + $(CAT) $(OUTPUT)/bundleout_images.csv \ + | perl -pe 's/(^|,|: )([^,:]+\/)([^,\/:]*\.)(net|cub)/\1\3\4/g' 2>/dev/null \ + | $(SED) 's/\([0-9][0-9]*\.[0-9][0-9][0-9][0-9][0-9][0-9]\)\([0-9][0-9]*\)/\1/g' \ + > $(OUTPUT)/rect-latFree_bundleout_images.csv; + $(RM) $(OUTPUT)/bundleout_images.csv > /dev/null; + $(MV) $(OUTPUT)/bundleout_points.csv $(OUTPUT)/rect-latFree_bundleout_points.csv > /dev/null; + $(RM) $(OUTPUT)/bundleout.txt print.prt > /dev/null; + $(RM) $(OUTPUT)/residuals.csv > /dev/null; +# $(RM) $(OUTPUT)/cube.lis print.prt > /dev/null; + +# test lat bundle and lat output with a free network (all points free) - (sigma 0 should match lat bundle with lat output + $(APPNAME) fromlist=$(OUTPUT)/cube.lis \ + cnet=$(INPUT)/Ames_free.net \ + onet=$(OUTPUT)/latFree_out.net \ + radius=yes \ + errorpropagation=yes \ + control_point_coordinate_type_bundle=LAT \ + control_point_coordinate_type_reports=LAT \ + file_prefix=$(OUTPUT)/ > /dev/null; + $(CAT) $(OUTPUT)/bundleout.txt | grep -v "Run Time:" | grep -v "Elapsed Time:" \ + | perl -pe 's/(^|,|: )([^,:]+\/)([^,\/:]*\.)(net|cub)/\1\3\4/g' 2>/dev/null \ + | $(SED) 's/\([0-9][0-9]*\.[0-9][0-9][0-9][0-9]\)\([0-9][0-9]*\)/\1/g' \ + | $(SED) s/`date +%Y-%m-%dT`\[0-2\]\[0-9\]:\[0-5\]\[0-9\]:\[0-5\]\[0-9\]/date/ \ + > $(OUTPUT)/latFree_bundleout.txt; + $(CAT) $(OUTPUT)/residuals.csv \ + | perl -pe 's/(^|,|: )([^,:]+\/)([^,\/:]*\.)(net|cub)/\1\3\4/g' 2>/dev/null \ + | $(SED) 's/\([0-9][0-9]*\.[0-9][0-9][0-9][0-9][0-9][0-9]\)\([0-9][0-9]*\)/\1/g' \ + > $(OUTPUT)/latFree_residuals.csv; + $(CAT) $(OUTPUT)/bundleout_images.csv \ + | perl -pe 's/(^|,|: )([^,:]+\/)([^,\/:]*\.)(net|cub)/\1\3\4/g' 2>/dev/null \ + | $(SED) 's/\([0-9][0-9]*\.[0-9][0-9][0-9][0-9][0-9][0-9]\)\([[0-9]0-9]*\)/\1/g' \ + > $(OUTPUT)/latFree_bundleout_images.csv; + $(RM) $(OUTPUT)/bundleout_images.csv > /dev/null; + $(MV) $(OUTPUT)/bundleout_points.csv $(OUTPUT)/latFree_bundleout_points.csv > /dev/null; + $(RM) $(OUTPUT)/bundleout.txt print.prt > /dev/null; + $(RM) $(OUTPUT)/residuals.csv > /dev/null; + $(RM) $(OUTPUT)/cube.lis print.prt > /dev/null; diff --git a/isis/src/control/apps/seedgrid/tsts/errors/errors.txt b/isis/src/control/apps/seedgrid/tsts/errors/errors.txt deleted file mode 100644 index b375d4ea9987a3daae62c1466edb33d6948d6adc..0000000000000000000000000000000000000000 --- a/isis/src/control/apps/seedgrid/tsts/errors/errors.txt +++ /dev/null @@ -1 +0,0 @@ -[2018-03-21 14:12:04] Failed ... No truth folder or files diff --git a/isis/src/control/objs/BundleAdjust/BundleAdjust.cpp b/isis/src/control/objs/BundleAdjust/BundleAdjust.cpp index 894a12d9f8d28ebec13a1206cb41b51bab7ab747..5ed7b22cae200e6f3fa8f6c3adc294e85cc5bfdf 100644 --- a/isis/src/control/objs/BundleAdjust/BundleAdjust.cpp +++ b/isis/src/control/objs/BundleAdjust/BundleAdjust.cpp @@ -104,7 +104,8 @@ namespace Isis { m_cleanUp = true; m_cnetFileName = cnetFile; try { - m_controlNet = ControlNetQsp( new ControlNet(cnetFile, &progress) ); + m_controlNet = ControlNetQsp( new ControlNet(cnetFile, &progress, + bundleSettings->controlPointCoordTypeReports()) ); } catch (IException &e) { throw; @@ -367,8 +368,6 @@ namespace Isis { // JWB // - some of these not originally initialized.. better values??? m_iteration = 0; - m_radiansToMeters = 0.0; - m_metersToRadians = 0.0; m_rank = 0; m_iterationSummary = ""; @@ -397,22 +396,6 @@ namespace Isis { // should we initialize objects m_xResiduals, m_yResiduals, m_xyResiduals - // (must be a smarter way) - // get target body radii and body specific conversion factors between radians and meters. - // need validity checks and different conversion factors for lat and long - // initialize m_bodyRadii - m_bodyRadii[0] = m_bodyRadii[1] = m_bodyRadii[2] = Distance(); - Camera *cnetCamera = m_controlNet->Camera(0); - if (cnetCamera) { - cnetCamera->radii(m_bodyRadii); // meters - - if (m_bodyRadii[0] >= Distance(0, Distance::Meters)) { - m_metersToRadians = 0.001 / m_bodyRadii[0].kilometers(); // at equator - m_radiansToMeters = 1.0 / m_metersToRadians; - m_bundleResults.setRadiansToMeters(m_radiansToMeters); - } - } - // TESTING // TODO: code below should go into a separate method??? // set up BundleObservations and assign solve settings for each from BundleSettings class @@ -459,11 +442,10 @@ namespace Isis { continue; } - BundleControlPointQsp bundleControlPoint(new BundleControlPoint(point)); + BundleControlPointQsp bundleControlPoint(new BundleControlPoint + (m_bundleSettings, point)); m_bundleControlPoints.append(bundleControlPoint); - bundleControlPoint->setWeights(m_bundleSettings, m_metersToRadians); - // set parent observation for each BundleMeasure int numMeasures = bundleControlPoint->size(); @@ -727,7 +709,7 @@ namespace Isis { // } // } - // Compute the apriori lat/lons for each nonheld point + // Compute the apriori coordinates for each nonheld point m_controlNet->ComputeApriori(); // original location // ken testing - if solving for target mean radius, set point radius to current mean radius @@ -744,7 +726,9 @@ namespace Isis { } } - if (m_bundleTargetBody && m_bundleTargetBody->solveTriaxialRadii()) { + // Only use target body solution options when using Latitudinal coordinates + if (m_bundleTargetBody && m_bundleTargetBody->solveTriaxialRadii() + && m_bundleSettings->controlPointCoordTypeBundle() == SurfacePoint::Latitudinal) { int numControlPoints = m_bundleControlPoints.size(); for (int i = 0; i < numControlPoints; i++) { BundleControlPointQsp point = m_bundleControlPoints.at(i); @@ -758,6 +742,7 @@ namespace Isis { } } + // Beginning of iterations m_iteration = 1; double vtpv = 0.0; double previousSigma0 = 0.0; @@ -787,7 +772,7 @@ namespace Isis { m_sparseNormals.zeroBlocks(); } - // form normal equations + // form normal equations -- computePartials is called in here. if (!formNormalEquations()) { m_bundleResults.setConverged(false); break; @@ -1309,6 +1294,7 @@ namespace Isis { Q.zeroBlocks(); // weighting of 3D point parameters + // Make sure weights are in the units corresponding to the bundle coordinate type boost::numeric::ublas::bounded_vector &weights = bundleControlPoint->weights(); boost::numeric::ublas::bounded_vector &corrections @@ -1337,7 +1323,7 @@ namespace Isis { // save upper triangular covariance matrix for error propagation SurfacePoint SurfacePoint = bundleControlPoint->adjustedSurfacePoint(); - SurfacePoint.SetSphericalMatrix(N22); + SurfacePoint.SetMatrix(m_bundleSettings->controlPointCoordTypeBundle(), N22); bundleControlPoint->setAdjustedSurfacePoint(SurfacePoint); // form Q (this is N22{-1} * N12{T}) @@ -1429,35 +1415,6 @@ namespace Isis { } - /** - * Perform the matrix multiplication v2 = alpha ( Q x v1 ). - * - * @param alpha A constant multiplier. - * @param v2 The output vector. - * @param Q A sparse block matrix. - * @param v1 A vector. - */ - void BundleAdjust::productAlphaAV(double alpha, bounded_vector &v2, - SparseBlockRowMatrix &Q, - vector &v1) { - - QMapIterator< int, LinearAlgebra::Matrix * > Qit(Q); - - int subrangeStart, subrangeEnd; - - while ( Qit.hasNext() ) { - Qit.next(); - - int columnIndex = Qit.key(); - - subrangeStart = m_sparseNormals.at(columnIndex)->startColumn(); - subrangeEnd = subrangeStart + Qit.value()->size2(); - - v2 += alpha * prod(*(Qit.value()),subrange(v1,subrangeStart,subrangeEnd)); - } - } - - /** * Perform the matrix multiplication Q = N22 x N12(transpose) * @@ -1850,7 +1807,7 @@ namespace Isis { * with the different partial derivatives. * * @param coeffTarget A matrix that will contain target body - * pertial derivatives. + * partial derivatives. * @param coeffImage A matrix that will contain camera position and orientation * partial derivatives. * @param coeffPoint3D A matrix that will contain point lat, lon, and radius @@ -1870,10 +1827,11 @@ namespace Isis { BundleMeasure &measure, BundleControlPoint &point) { - // additional vectors - std::vector lookBWRTLat; - std::vector lookBWRTLon; - std::vector lookBWRTRad; + // These vectors are either body-fixed latitudinal (lat/lon/radius) or rectangular (x/y/z) + // depending on the value of coordinate type in SurfacePoint + std::vector lookBWRTCoord1; + std::vector lookBWRTCoord2; + std::vector lookBWRTCoord3; Camera *measureCamera = NULL; @@ -1909,8 +1867,10 @@ namespace Isis { // no need to call SetImage for framing camera ( CameraType = 0 ) if (measureCamera->GetCameraType() != 0) { - // Set the Spice to the measured point - // TODO - can we explain this better? + // Set the Spice to the measured point. A framing camera exposes the entire image at one time. + // It will have a single set of Spice for the entire image. Scanning cameras may populate a single + // image with multiple exposures, each with a unique set of Spice. SetImage needs to be called + // repeatedly for these images to point to the Spice for the current pixel. measureCamera->SetImage(measure.sample(), measure.line()); } @@ -1927,13 +1887,12 @@ namespace Isis { throw IException(IException::User, msg, _FILEINFO_); } - // partials for fixed point w/r lat, long, radius in Body-Fixed - lookBWRTLat = measureCamera->GroundMap()->PointPartial(point.adjustedSurfacePoint(), - CameraGroundMap::WRT_Latitude); - lookBWRTLon = measureCamera->GroundMap()->PointPartial(point.adjustedSurfacePoint(), - CameraGroundMap::WRT_Longitude); - lookBWRTRad = measureCamera->GroundMap()->PointPartial(point.adjustedSurfacePoint(), - CameraGroundMap::WRT_Radius); + // Retrieve the coordinate type (latitudinal or rectangular) and compute the partials for + // the fixed point with respect to each coordinate in Body-Fixed + SurfacePoint::CoordinateType type = m_bundleSettings->controlPointCoordTypeBundle(); + lookBWRTCoord1 = point.adjustedSurfacePoint().Partial(type, SurfacePoint::One); + lookBWRTCoord2 = point.adjustedSurfacePoint().Partial(type, SurfacePoint::Two); + lookBWRTCoord3 = point.adjustedSurfacePoint().Partial(type, SurfacePoint::Three); int index = 0; if (m_bundleSettings->solveTargetBody() && m_bundleSettings->solvePoleRA()) { @@ -2083,14 +2042,14 @@ namespace Isis { } } - // partials for 3D point - measureCamera->GroundMap()->GetdXYdPoint(lookBWRTLat, + // Complete partials calculations for 3D point (latitudinal or rectangular) + measureCamera->GroundMap()->GetdXYdPoint(lookBWRTCoord1, &coeffPoint3D(0, 0), &coeffPoint3D(1, 0)); - measureCamera->GroundMap()->GetdXYdPoint(lookBWRTLon, + measureCamera->GroundMap()->GetdXYdPoint(lookBWRTCoord2, &coeffPoint3D(0, 1), &coeffPoint3D(1, 1)); - measureCamera->GroundMap()->GetdXYdPoint(lookBWRTRad, + measureCamera->GroundMap()->GetdXYdPoint(lookBWRTCoord3, &coeffPoint3D(0, 2), &coeffPoint3D(1, 2)); @@ -2172,14 +2131,12 @@ namespace Isis { t += numParameters; } - - // TODO: Below code should move into BundleControlPoint->updateParameterCorrections - // except, what about the productAlphaAV method? + // TODO - When BundleXYZ gets merged into dev, go with Ken's version of merging the updating of + // of the adjusted surface point into BundleControlPoint. - // Update lat/lon for each control point - double latCorrection, lonCorrection, radCorrection; int pointIndex = 0; int numControlPoints = m_bundleControlPoints.size(); + for (int i = 0; i < numControlPoints; i++) { BundleControlPointQsp point = m_bundleControlPoints.at(i); @@ -2188,78 +2145,8 @@ namespace Isis { continue; } - // get NIC, Q, and correction vector for this point - boost::numeric::ublas::bounded_vector< double, 3 > &NIC = point->nicVector(); - SparseBlockRowMatrix &Q = point->cholmodQMatrix(); - boost::numeric::ublas::bounded_vector< double, 3 > &corrections = point->corrections(); - - // subtract product of Q and nj from NIC - productAlphaAV(-1.0, NIC, Q, m_imageSolution); - - // get point parameter corrections - latCorrection = NIC(0); - lonCorrection = NIC(1); - radCorrection = NIC(2); - - SurfacePoint surfacepoint = point->adjustedSurfacePoint(); - - double pointLat = surfacepoint.GetLatitude().degrees(); - double pointLon = surfacepoint.GetLongitude().degrees(); - double pointRad = surfacepoint.GetLocalRadius().meters(); - - pointLat += RAD2DEG * latCorrection; - pointLon += RAD2DEG * lonCorrection; - - // Make sure updated values are still in valid range. - // TODO What is the valid lon range? - if (pointLat < -90.0) { - pointLat = -180.0 - pointLat; - pointLon = pointLon + 180.0; - } - if (pointLat > 90.0) { - pointLat = 180.0 - pointLat; - pointLon = pointLon + 180.0; - } - while (pointLon > 360.0) { - pointLon = pointLon - 360.0; - } - while (pointLon < 0.0) { - pointLon = pointLon + 360.0; - } - - pointRad += 1000.*radCorrection; - - // sum and save corrections - corrections(0) += latCorrection; - corrections(1) += lonCorrection; - corrections(2) += radCorrection; - - // ken testing - if solving for target body mean radius, set radius to current - // mean radius value - if (m_bundleTargetBody && (m_bundleTargetBody->solveMeanRadius() - || m_bundleTargetBody->solveTriaxialRadii())) { - if (m_bundleTargetBody->solveMeanRadius()) { - surfacepoint.SetSphericalCoordinates(Latitude(pointLat, Angle::Degrees), - Longitude(pointLon, Angle::Degrees), - m_bundleTargetBody->meanRadius()); - } - else if (m_bundleTargetBody->solveTriaxialRadii()) { - Distance localRadius = m_bundleTargetBody-> - localRadius(Latitude(pointLat, Angle::Degrees), - Longitude(pointLon, Angle::Degrees)); - surfacepoint.SetSphericalCoordinates(Latitude(pointLat, Angle::Degrees), - Longitude(pointLon, Angle::Degrees), - localRadius); - } - } - else { - surfacepoint.SetSphericalCoordinates(Latitude(pointLat, Angle::Degrees), - Longitude(pointLon, Angle::Degrees), - Distance(pointRad, Distance::Meters)); - } - - point->setAdjustedSurfacePoint(surfacepoint); - + point->applyParameterCorrections(m_imageSolution, m_sparseNormals, + m_bundleTargetBody); pointIndex++; } // end loop over point corrections @@ -2325,7 +2212,7 @@ namespace Isis { } // add vtpv from constrained 3D points - int pointIndex = 0; + int pointIndex = 0; // *** TODO *** This does not appear to be used. Delete? DAC 07-14-2017 for (int i = 0; i < numObjectPoints; i++) { BundleControlPointQsp bundleControlPoint = m_bundleControlPoints.at(i); @@ -2685,6 +2572,12 @@ namespace Isis { * us to create the inverse matrix correlation file. References #4315. * @history 2016-10-28 Ian Humphrey - Added extra newline between Error Propagation: Inverse * Blocking and Filling point covariance messages. References #4463. + * @history 2018-09-06 Debbie A. Cook and Ken Edmundson - (added to BundleXYZ + * branch on (2018-05-31). Moved productAlphaAV and control point + * parameter correction code to BundleControlPoint. Earlier revised + * errorPropagation to compute the sigmas via the variance/ + * covariance matrices instead of the sigmas. This should produce + * more accurate results. References #4649 and #501. */ bool BundleAdjust::errorPropagation() { emit(statusBarUpdate("Error Propagation")); @@ -2693,8 +2586,8 @@ namespace Isis { cholmod_free_sparse(&m_cholmodNormal, &m_cholmodCommon); LinearAlgebra::Matrix T(3, 3); - double sigmaLat, sigmaLon, sigmaRad; - double t; + // *** TODO *** + // Can any of the control point specific code be moved to BundleControlPoint? double sigma0Squared = m_bundleResults.sigma0() * m_bundleResults.sigma0(); @@ -2942,6 +2835,7 @@ namespace Isis { outputBundleStatus("\n\n"); // now loop over points again and set final covariance stuff + // *** TODO *** Can this loop go into BundleControlPoint int pointIndex = 0; for (j = 0; j < numObjectPoints; j++) { @@ -2963,37 +2857,70 @@ namespace Isis { // get corresponding point covariance matrix boost::numeric::ublas::symmetric_matrix &covariance = pointCovariances[pointIndex]; - // Ask Ken what is happening here...Setting just the sigmas is not very accurate - // Shouldn't we be updating and setting the matrix??? TODO + // Update and reset the matrix + // Get the Limiting Error Propagation uncertainties: sigmas for coordinate 1, 2, and 3 in meters + // SurfacePoint SurfacePoint = point->adjustedSurfacePoint(); - sigmaLat = SurfacePoint.GetLatSigma().radians(); - sigmaLon = SurfacePoint.GetLonSigma().radians(); - sigmaRad = SurfacePoint.GetLocalRadiusSigma().meters(); - - t = sigmaLat * sigmaLat + covariance(0, 0); - Distance latSigmaDistance(sqrt(sigma0Squared * t) * m_radiansToMeters, Distance::Meters); - - t = sigmaLon * sigmaLon + covariance(1, 1); - t = sqrt(sigma0Squared * t) * m_radiansToMeters; - Distance lonSigmaDistance( - t * cos(point->adjustedSurfacePoint().GetLatitude().radians()), - Distance::Meters); - - t = sigmaRad*sigmaRad + covariance(2, 2); - t = sqrt(sigma0Squared * t) * 1000.0; - - SurfacePoint.SetSphericalSigmasDistance(latSigmaDistance, lonSigmaDistance, - Distance(t, Distance::Meters)); - + // Get the TEP by adding the corresponding members of pCovar and covariance + boost::numeric::ublas::symmetric_matrix pCovar; + + if (m_bundleSettings->controlPointCoordTypeBundle() == SurfacePoint::Latitudinal) { + pCovar = SurfacePoint.GetSphericalMatrix(SurfacePoint::Kilometers); + } + else { + // Assume Rectangular coordinates + pCovar = SurfacePoint.GetRectangularMatrix(SurfacePoint::Kilometers); + } + pCovar += covariance; + pCovar *= sigma0Squared; + + // debug lines + // if (j < 3) { + // std::cout << " Adjusted surface point ..." << std::endl; + // std:: cout << " sigmaLat (radians) = " << sqrt(pCovar(0,0)) << std::endl; + // std:: cout << " sigmaLon (radians) = " << sqrt(pCovar(1,1)) << std::endl; + // std:: cout << " sigmaRad (km) = " << sqrt(pCovar(2,2)) << std::endl; + // std::cout << " Adjusted matrix = " << std::endl; + // std::cout << " " << pCovar(0,0) << " " << pCovar(0,1) << " " + // << pCovar(0,2) << std::endl; + // std::cout << " " << pCovar(1,0) << " " << pCovar(1,1) << " " + // << pCovar(1,2) << std::endl; + // std::cout << " " << pCovar(2,0) << " " << pCovar(2,1) << " " + // << pCovar(2,2) << std::endl; + // } + // end debug + + // Distance units are km**2 + SurfacePoint.SetMatrix(m_bundleSettings->controlPointCoordTypeBundle(),pCovar); point->setAdjustedSurfacePoint(SurfacePoint); + // // debug lines + // if (j < 3) { + // boost::numeric::ublas::symmetric_matrix recCovar; + // recCovar = SurfacePoint.GetRectangularMatrix(SurfacePoint::Meters); + // std:: cout << " sigmaLat (meters) = " << + // point->adjustedSurfacePoint().GetSigmaDistance(SurfacePoint::Latitudinal, + // SurfacePoint::One).meters() << std::endl; + // std:: cout << " sigmaLon (meters) = " << + // point->adjustedSurfacePoint().GetSigmaDistance(SurfacePoint::Latitudinal, + // SurfacePoint::Two).meters() << std::endl; + // std:: cout << " sigmaRad (km) = " << sqrt(pCovar(2,2)) << std::endl; + // std::cout << "Rectangular matrix with radius in meters" << std::endl; + // std::cout << " " << recCovar(0,0) << " " << recCovar(0,1) << " " + // << recCovar(0,2) << std::endl; + // std::cout << " " << recCovar(1,0) << " " << recCovar(1,1) << " " + // << recCovar(1,2) << std::endl; + // std::cout << " " << recCovar(2,0) << " " << recCovar(2,1) << " " + // << recCovar(2,2) << std::endl; + // } + // // end debug pointIndex++; } return true; } - + /** * Returns a pointer to the output control network. @@ -3269,31 +3196,36 @@ namespace Isis { if (m_bundleSettings->errorPropagation()) { - // initialize lat/lon/rad boundaries - Distance minSigmaLatDist; - QString minSigmaLatPointId = ""; - - Distance maxSigmaLatDist; - QString maxSigmaLatPointId = ""; - - Distance minSigmaLonDist; - QString minSigmaLonPointId = ""; + // initialize body-fixed coordinate boundaries - Distance maxSigmaLonDist; - QString maxSigmaLonPointId = ""; + // Latitude or X + Distance minSigmaCoord1Dist; + QString minSigmaCoord1PointId = ""; + + Distance maxSigmaCoord1Dist; + QString maxSigmaCoord1PointId = ""; + + // Longitude or Y + Distance minSigmaCoord2Dist; + QString minSigmaCoord2PointId = ""; - Distance minSigmaRadDist; - QString minSigmaRadPointId = ""; + Distance maxSigmaCoord2Dist; + QString maxSigmaCoord2PointId = ""; - Distance maxSigmaRadDist; - QString maxSigmaRadPointId = ""; + // Radius or Z + Distance minSigmaCoord3Dist; + QString minSigmaCoord3PointId = ""; + Distance maxSigmaCoord3Dist; + QString maxSigmaCoord3PointId = ""; + // compute stats for point sigmas - Statistics sigmaLatStats; - Statistics sigmaLonStats; - Statistics sigmaRadStats; + Statistics sigmaCoord1Stats; + Statistics sigmaCoord2Stats; + Statistics sigmaCoord3Stats; - Distance sigmaLatDist, sigmaLonDist, sigmaRadDist; + Distance sigmaCoord1Dist, sigmaCoord2Dist, sigmaCoord3Dist; + SurfacePoint::CoordinateType type = m_bundleSettings->controlPointCoordTypeReports(); int numPoints = m_bundleControlPoints.size(); // initialize max and min values to those from first valid point @@ -3301,23 +3233,27 @@ namespace Isis { const BundleControlPointQsp point = m_bundleControlPoints.at(i); - maxSigmaLatDist = point->adjustedSurfacePoint().GetLatSigmaDistance();; - minSigmaLatDist = maxSigmaLatDist; + maxSigmaCoord1Dist = point->adjustedSurfacePoint().GetSigmaDistance(type, + SurfacePoint::One); + minSigmaCoord1Dist = maxSigmaCoord1Dist; - maxSigmaLonDist = point->adjustedSurfacePoint().GetLonSigmaDistance();; - minSigmaLonDist = maxSigmaLonDist; + maxSigmaCoord2Dist = point->adjustedSurfacePoint().GetSigmaDistance(type, + SurfacePoint::Two); + minSigmaCoord2Dist = maxSigmaCoord2Dist; - maxSigmaLatPointId = point->id(); - maxSigmaLonPointId = maxSigmaLatPointId; - minSigmaLatPointId = maxSigmaLatPointId; - minSigmaLonPointId = maxSigmaLatPointId; + maxSigmaCoord1PointId = point->id(); + maxSigmaCoord2PointId = maxSigmaCoord1PointId; + minSigmaCoord1PointId = maxSigmaCoord1PointId; + minSigmaCoord2PointId = maxSigmaCoord1PointId; - if (m_bundleSettings->solveRadius()) { - maxSigmaRadDist = point->adjustedSurfacePoint().GetLocalRadiusSigma(); - minSigmaRadDist = maxSigmaRadDist; + // Get stats for coordinate 3 if used + if (m_bundleSettings->solveRadius() || type == SurfacePoint::Rectangular) { + maxSigmaCoord3Dist = point->adjustedSurfacePoint().GetSigmaDistance(type, + SurfacePoint::Three); + minSigmaCoord3Dist = maxSigmaCoord3Dist; - maxSigmaRadPointId = maxSigmaLatPointId; - minSigmaRadPointId = maxSigmaLatPointId; + maxSigmaCoord3PointId = maxSigmaCoord1PointId; + minSigmaCoord3PointId = maxSigmaCoord1PointId; } break; } @@ -3326,40 +3262,43 @@ namespace Isis { const BundleControlPointQsp point = m_bundleControlPoints.at(i); - sigmaLatDist = point->adjustedSurfacePoint().GetLatSigmaDistance(); - sigmaLonDist = point->adjustedSurfacePoint().GetLonSigmaDistance(); - sigmaRadDist = point->adjustedSurfacePoint().GetLocalRadiusSigma(); + sigmaCoord1Dist = point->adjustedSurfacePoint().GetSigmaDistance(type, + SurfacePoint::One); + sigmaCoord2Dist = point->adjustedSurfacePoint().GetSigmaDistance(type, + SurfacePoint::Two); + sigmaCoord3Dist = point->adjustedSurfacePoint().GetSigmaDistance(type, + SurfacePoint::Three); - sigmaLatStats.AddData(sigmaLatDist.meters()); - sigmaLonStats.AddData(sigmaLonDist.meters()); - sigmaRadStats.AddData(sigmaRadDist.meters()); + sigmaCoord1Stats.AddData(sigmaCoord1Dist.meters()); + sigmaCoord2Stats.AddData(sigmaCoord2Dist.meters()); + sigmaCoord3Stats.AddData(sigmaCoord3Dist.meters()); - if (sigmaLatDist > maxSigmaLatDist) { - maxSigmaLatDist = sigmaLatDist; - maxSigmaLatPointId = point->id(); + if (sigmaCoord1Dist > maxSigmaCoord1Dist) { + maxSigmaCoord1Dist = sigmaCoord1Dist; + maxSigmaCoord1PointId = point->id(); } - if (sigmaLonDist > maxSigmaLonDist) { - maxSigmaLonDist = sigmaLonDist; - maxSigmaLonPointId = point->id(); + if (sigmaCoord2Dist > maxSigmaCoord2Dist) { + maxSigmaCoord2Dist = sigmaCoord2Dist; + maxSigmaCoord2PointId = point->id(); } - if (m_bundleSettings->solveRadius()) { - if (sigmaRadDist > maxSigmaRadDist) { - maxSigmaRadDist = sigmaRadDist; - maxSigmaRadPointId = point->id(); + if (m_bundleSettings->solveRadius() || type == SurfacePoint::Rectangular) { + if (sigmaCoord3Dist > maxSigmaCoord3Dist) { + maxSigmaCoord3Dist = sigmaCoord3Dist; + maxSigmaCoord3PointId = point->id(); } } - if (sigmaLatDist < minSigmaLatDist) { - minSigmaLatDist = sigmaLatDist; - minSigmaLatPointId = point->id(); + if (sigmaCoord1Dist < minSigmaCoord1Dist) { + minSigmaCoord1Dist = sigmaCoord1Dist; + minSigmaCoord1PointId = point->id(); } - if (sigmaLonDist < minSigmaLonDist) { - minSigmaLonDist = sigmaLonDist; - minSigmaLonPointId = point->id(); + if (sigmaCoord2Dist < minSigmaCoord2Dist) { + minSigmaCoord2Dist = sigmaCoord2Dist; + minSigmaCoord2PointId = point->id(); } - if (m_bundleSettings->solveRadius()) { - if (sigmaRadDist < minSigmaRadDist) { - minSigmaRadDist = sigmaRadDist; - minSigmaRadPointId = point->id(); + if (m_bundleSettings->solveRadius() || type == SurfacePoint::Rectangular) { + if (sigmaCoord3Dist < minSigmaCoord3Dist) { + minSigmaCoord3Dist = sigmaCoord3Dist; + minSigmaCoord3PointId = point->id(); } } } @@ -3367,18 +3306,18 @@ namespace Isis { // update bundle results m_bundleResults.resizeSigmaStatisticsVectors(numberImages); - m_bundleResults.setSigmaLatitudeRange(minSigmaLatDist, maxSigmaLatDist, - minSigmaLatPointId, maxSigmaLatPointId); + m_bundleResults.setSigmaCoord1Range(minSigmaCoord1Dist, maxSigmaCoord1Dist, + minSigmaCoord1PointId, maxSigmaCoord1PointId); - m_bundleResults.setSigmaLongitudeRange(minSigmaLonDist, maxSigmaLonDist, - minSigmaLonPointId, maxSigmaLonPointId); + m_bundleResults.setSigmaCoord2Range(minSigmaCoord2Dist, maxSigmaCoord2Dist, + minSigmaCoord2PointId, maxSigmaCoord2PointId); - m_bundleResults.setSigmaRadiusRange(minSigmaRadDist, maxSigmaRadDist, - minSigmaRadPointId, maxSigmaRadPointId); + m_bundleResults.setSigmaCoord3Range(minSigmaCoord3Dist, maxSigmaCoord3Dist, + minSigmaCoord3PointId, maxSigmaCoord3PointId); - m_bundleResults.setRmsFromSigmaStatistics(sigmaLatStats.Rms(), - sigmaLonStats.Rms(), - sigmaRadStats.Rms()); + m_bundleResults.setRmsFromSigmaStatistics(sigmaCoord1Stats.Rms(), + sigmaCoord2Stats.Rms(), + sigmaCoord3Stats.Rms()); } m_bundleResults.setRmsImageResidualLists(rmsImageLineResiduals.toList(), rmsImageSampleResiduals.toList(), diff --git a/isis/src/control/objs/BundleAdjust/BundleAdjust.h b/isis/src/control/objs/BundleAdjust/BundleAdjust.h index 715c62037706d16c201922f8ad8acd567e58d168..c5d64f9746051180eac96695930a2bd2e8d7477d 100644 --- a/isis/src/control/objs/BundleAdjust/BundleAdjust.h +++ b/isis/src/control/objs/BundleAdjust/BundleAdjust.h @@ -269,7 +269,7 @@ namespace Isis { * there is no longer a -Wformat-security warning. * @history 2017-05-01 Makayla Shepherd - Added imageLists() to track and return the images * bundled. Fixes #4818. - * @history 2017-05-09 Tracie Sucharski - Fixed an empty pointer in ::imgeLists method. + * @history 2017-05-09 Tracie Sucharski - Fixed an empty pointer in ::imgeLists method. * @history 2017-05-09 Ken Edmundson - Speed improvements and error propagation bug fix. * Separated initializations for Normal Equations matrix out of * ::initializeCholmodLibraryVariables() into @@ -285,6 +285,16 @@ namespace Isis { * @history 2017-08-09 Summer Stapleton - Added a try/catch around the m_controlNet assignment * in each of the constructors to verify valid control net input. * Fixes #5068. + * @history 2017-09-01 Debbie A. Cook - Added BundleSettingsQsp as argument to + * BundleControlPoint constructor and moved setWeights call from + * BundleAdjust::init to BundleControlPoint constructor. Don't allow + * solving for triaxial radii when coordinate type is not Latitudinal. + * Added new optional argument controlPointCoordType to ControlNet + * constructor call. References #4649 and #501. + * @history 2018-05-31 Debbie A. Cook - Moved productAlphaAV and control point parameter + * correction code to BundleControlPoint. Earlier revised errorPropagation to + * compute the sigmas via the variance/covariance matrices instead of the sigmas. + * This should produce more accurate results. References #4649 and #501. * @history 2018-05-22 Ken Edmundson - Modified methods bundleSolveInformation() and * solveCholeskyBR() to return raw pointers to a BundleSolutionInfo object. * Also modified resultsReady signal to take a raw pointer to a @@ -294,8 +304,25 @@ namespace Isis { * instead of a raw pointer. * @history 2018-06-14 Christopher Combs - Added getter method to tell if a bundle adjust was * aborted. Added emits for status updates to the run widget. - * @history 2018-06-18 Makayla Shepherd - Stopped command line output for ipce BundleAdjust. + * @history 2018-06-18 Makayla Shepherd - Stopped command line output for ipce BundleAdjust. * Fixes #4171. + * @history 2018-09-06 Debbie A. Cook - (added to BundleXYZ branch on 2017-09-01) + * Added BundleSettingsQsp as argument to BundleControlPoint constructor + * and moved setWeights call from BundleAdjust::init to BundleControlPoint + * constructor. Don't allow solving for triaxial radii when coordinate type + * is not Latitudinal. Added new optional argument controlPointCoordType + * to ControlNet constructor call. References #4649 and #501. + * @history 2018-09-06 Debbie A. Cook and Ken Edmundson - (added to BundleXYZ + * branch on (2018-05-31). Moved productAlphaAV and control point + * parameter correction code to BundleControlPoint. Earlier revised + * errorPropagation to compute the sigmas via the variance/ + * covariance matrices instead of the sigmas. This should produce + * more accurate results. References #4649 and #501. + * @history 2018-09-06 Debbie A. Cook - Removed obsolete member variables: + * m_radiansToMeters, m_metersToRadians, and m_bodyRadii + * which have been replaced with the local radius of a control + * point for converting point sigmas to/from radians from/to meters. + * References #4649 and #501. */ class BundleAdjust : public QObject { Q_OBJECT @@ -447,7 +474,6 @@ namespace Isis { SerialNumberList *m_serialNumberList; //!< List of image serial numbers. BundleTargetBodyQsp m_bundleTargetBody; /**!< Contains information about the target body.*/ - Distance m_bodyRadii[3]; //!< Triaxial body radii in meters. bool m_abort; //!< If the bundle should abort. QString m_iterationSummary; /**!< Summary of the most recently completed iteration.*/ @@ -460,10 +486,6 @@ namespace Isis { int m_rank; //!< The rank of the system. int m_iteration; //!< The current iteration. int m_numberOfImagePartials; //!< number of image-related partials. - double m_radiansToMeters; /**!< The body specific radians to - meters conversion factor.*/ - double m_metersToRadians; /**!< The body specific meters to - radians conversion factor.*/ QList m_imageLists; /**!< The lists of images used in the bundle.*/ @@ -504,7 +526,7 @@ namespace Isis { cholmod_factorize.*/ LinearAlgebra::Vector m_imageSolution; /**!< The image parameter solution vector.*/ - + int m_previousNumberImagePartials; /**!< used in ::computePartials method to avoid unnecessary resizing of the coeffImage matrix.*/ diff --git a/isis/src/control/objs/BundleResults/BundleResults.cpp b/isis/src/control/objs/BundleResults/BundleResults.cpp index 7ee446184d13d8875c14d4b6b634ef08cbd44823..3d7c1d295402d2177b1e40b1996cd26637cb9d7e 100644 --- a/isis/src/control/objs/BundleResults/BundleResults.cpp +++ b/isis/src/control/objs/BundleResults/BundleResults.cpp @@ -33,7 +33,7 @@ using namespace boost::numeric::ublas; namespace Isis { /** - * Constructs a BundleSettings object. + * Constructs a BundleResults object. * * @param parent The Qt-relationship parent. */ @@ -53,7 +53,7 @@ namespace Isis { /** - * Construct this BundleSettings object from XML. + * Construct this BundleResults object from XML. * * @param bundleSettingsFolder Where the settings XML for this bundle adjustment * resides - /work/.../projectRoot/images/import1 @@ -73,7 +73,7 @@ namespace Isis { /** - * Copy constructor for BundleResults. Creates this BundleSettings object as a copy + * Copy constructor for BundleResults. Creates this BundleResults object as a copy * of another BundleResults object. * * @param src The other BundleResults object to be copied. @@ -98,7 +98,6 @@ namespace Isis { m_sigma0(src.m_sigma0), m_elapsedTime(src.m_elapsedTime), m_elapsedTimeErrorProp(src.m_elapsedTimeErrorProp), - m_radiansToMeters(src.m_radiansToMeters), m_converged(src.m_converged), m_bundleControlPoints(src.m_bundleControlPoints), m_outNet(src.m_outNet), @@ -113,21 +112,21 @@ namespace Isis { m_rmsImageRASigmas(src.m_rmsImageRASigmas), m_rmsImageDECSigmas(src.m_rmsImageDECSigmas), m_rmsImageTWISTSigmas(src.m_rmsImageTWISTSigmas), - m_minSigmaLatitudeDistance(src.m_minSigmaLatitudeDistance), - m_maxSigmaLatitudeDistance(src.m_maxSigmaLatitudeDistance), - m_minSigmaLongitudeDistance(src.m_minSigmaLongitudeDistance), - m_maxSigmaLongitudeDistance(src.m_maxSigmaLongitudeDistance), - m_minSigmaRadiusDistance(src.m_minSigmaRadiusDistance), - m_maxSigmaRadiusDistance(src.m_maxSigmaRadiusDistance), - m_minSigmaLatitudePointId(src.m_minSigmaLatitudePointId), - m_maxSigmaLatitudePointId(src.m_maxSigmaLatitudePointId), - m_minSigmaLongitudePointId(src.m_minSigmaLongitudePointId), - m_maxSigmaLongitudePointId(src.m_maxSigmaLongitudePointId), - m_minSigmaRadiusPointId(src.m_minSigmaRadiusPointId), - m_maxSigmaRadiusPointId(src.m_maxSigmaRadiusPointId), - m_rmsSigmaLatitudeStats(src.m_rmsSigmaLatitudeStats), - m_rmsSigmaLongitudeStats(src.m_rmsSigmaLongitudeStats), - m_rmsSigmaRadiusStats(src.m_rmsSigmaRadiusStats), + m_minSigmaCoord1Distance(src.m_minSigmaCoord1Distance), + m_maxSigmaCoord1Distance(src.m_maxSigmaCoord1Distance), + m_minSigmaCoord2Distance(src.m_minSigmaCoord2Distance), + m_maxSigmaCoord2Distance(src.m_maxSigmaCoord2Distance), + m_minSigmaCoord3Distance(src.m_minSigmaCoord3Distance), + m_maxSigmaCoord3Distance(src.m_maxSigmaCoord3Distance), + m_minSigmaCoord1PointId(src.m_minSigmaCoord1PointId), + m_maxSigmaCoord1PointId(src.m_maxSigmaCoord1PointId), + m_minSigmaCoord2PointId(src.m_minSigmaCoord2PointId), + m_maxSigmaCoord2PointId(src.m_maxSigmaCoord2PointId), + m_minSigmaCoord3PointId(src.m_minSigmaCoord3PointId), + m_maxSigmaCoord3PointId(src.m_maxSigmaCoord3PointId), + m_rmsSigmaCoord1Stats(src.m_rmsSigmaCoord1Stats), + m_rmsSigmaCoord2Stats(src.m_rmsSigmaCoord2Stats), + m_rmsSigmaCoord3Stats(src.m_rmsSigmaCoord3Stats), m_maximumLikelihoodFunctions(src.m_maximumLikelihoodFunctions), m_maximumLikelihoodIndex(src.m_maximumLikelihoodIndex), m_cumPro(new StatCumProbDistDynCalc(*src.m_cumPro)), @@ -184,7 +183,6 @@ namespace Isis { m_sigma0 = src.m_sigma0; m_elapsedTime = src.m_elapsedTime; m_elapsedTimeErrorProp = src.m_elapsedTimeErrorProp; - m_radiansToMeters = src.m_radiansToMeters; m_converged = src.m_converged; m_bundleControlPoints = src.m_bundleControlPoints; m_outNet = src.m_outNet; @@ -199,21 +197,21 @@ namespace Isis { m_rmsImageRASigmas = src.m_rmsImageRASigmas; m_rmsImageDECSigmas = src.m_rmsImageDECSigmas; m_rmsImageTWISTSigmas = src.m_rmsImageTWISTSigmas; - m_minSigmaLatitudeDistance = src.m_minSigmaLatitudeDistance; - m_maxSigmaLatitudeDistance = src.m_maxSigmaLatitudeDistance; - m_minSigmaLongitudeDistance = src.m_minSigmaLongitudeDistance; - m_maxSigmaLongitudeDistance = src.m_maxSigmaLongitudeDistance; - m_minSigmaRadiusDistance = src.m_minSigmaRadiusDistance; - m_maxSigmaRadiusDistance = src.m_maxSigmaRadiusDistance; - m_minSigmaLatitudePointId = src.m_minSigmaLatitudePointId; - m_maxSigmaLatitudePointId = src.m_maxSigmaLatitudePointId; - m_minSigmaLongitudePointId = src.m_minSigmaLongitudePointId; - m_maxSigmaLongitudePointId = src.m_maxSigmaLongitudePointId; - m_minSigmaRadiusPointId = src.m_minSigmaRadiusPointId; - m_maxSigmaRadiusPointId = src.m_maxSigmaRadiusPointId; - m_rmsSigmaLatitudeStats = src.m_rmsSigmaLatitudeStats; - m_rmsSigmaLongitudeStats = src.m_rmsSigmaLongitudeStats; - m_rmsSigmaRadiusStats = src.m_rmsSigmaRadiusStats; + m_minSigmaCoord1Distance = src.m_minSigmaCoord1Distance; + m_maxSigmaCoord1Distance = src.m_maxSigmaCoord1Distance; + m_minSigmaCoord2Distance = src.m_minSigmaCoord2Distance; + m_maxSigmaCoord2Distance = src.m_maxSigmaCoord2Distance; + m_minSigmaCoord3Distance = src.m_minSigmaCoord3Distance; + m_maxSigmaCoord3Distance = src.m_maxSigmaCoord3Distance; + m_minSigmaCoord1PointId = src.m_minSigmaCoord1PointId; + m_maxSigmaCoord1PointId = src.m_maxSigmaCoord1PointId; + m_minSigmaCoord2PointId = src.m_minSigmaCoord2PointId; + m_maxSigmaCoord2PointId = src.m_maxSigmaCoord2PointId; + m_minSigmaCoord3PointId = src.m_minSigmaCoord3PointId; + m_maxSigmaCoord3PointId = src.m_maxSigmaCoord3PointId; + m_rmsSigmaCoord1Stats = src.m_rmsSigmaCoord1Stats; + m_rmsSigmaCoord2Stats = src.m_rmsSigmaCoord2Stats; + m_rmsSigmaCoord3Stats = src.m_rmsSigmaCoord3Stats; m_maximumLikelihoodFunctions = src.m_maximumLikelihoodFunctions; m_maximumLikelihoodIndex = src.m_maximumLikelihoodIndex; @@ -257,23 +255,24 @@ namespace Isis { m_rmsImageDECSigmas.clear(); m_rmsImageTWISTSigmas.clear(); - // initialize lat/lon/rad boundaries - m_minSigmaLatitudeDistance.setMeters(1.0e+12); - m_maxSigmaLatitudeDistance.setMeters(0.0); - m_minSigmaLongitudeDistance.setMeters(1.0e+12); - m_maxSigmaLongitudeDistance.setMeters(0.0);; - m_minSigmaRadiusDistance.setMeters(1.0e+12); - m_maxSigmaRadiusDistance.setMeters(0.0); - m_minSigmaLatitudePointId = ""; - m_maxSigmaLatitudePointId = ""; - m_minSigmaLongitudePointId = ""; - m_maxSigmaLongitudePointId = ""; - m_minSigmaRadiusPointId = ""; - m_maxSigmaRadiusPointId = ""; - - m_rmsSigmaLatitudeStats = 0.0; - m_rmsSigmaLongitudeStats = 0.0; - m_rmsSigmaRadiusStats = 0.0; + // Initialize coordinate sigma boundaries. Units are meters for sigmas in both + // latitudinal and rectangular coordinates + m_minSigmaCoord1Distance.setMeters(1.0e+12); + m_maxSigmaCoord1Distance.setMeters(0.0); + m_minSigmaCoord2Distance.setMeters(1.0e+12); + m_maxSigmaCoord2Distance.setMeters(0.0);; + m_minSigmaCoord3Distance.setMeters(1.0e+12); + m_maxSigmaCoord3Distance.setMeters(0.0); + m_minSigmaCoord1PointId = ""; + m_maxSigmaCoord1PointId = ""; + m_minSigmaCoord2PointId = ""; + m_maxSigmaCoord2PointId = ""; + m_minSigmaCoord3PointId = ""; + m_maxSigmaCoord3PointId = ""; + + m_rmsSigmaCoord1Stats = 0.0; + m_rmsSigmaCoord2Stats = 0.0; + m_rmsSigmaCoord3Stats = 0.0; // set by compute residuals @@ -316,7 +315,6 @@ namespace Isis { m_maximumLikelihoodFunctions.clear(); m_cumProRes = NULL; - m_radiansToMeters = 0; m_observations.clear(); m_outNet.clear(); @@ -367,70 +365,70 @@ namespace Isis { /** - * Sets the min and max sigma latitude distances and point ids. + * Sets the min and max sigma distances and point ids for coordinate 1. * * @param minLatDist The new minimum sigma latitude distance. * @param maxLatDist The new maximum sigma latitude distance. * @param minLatPointId The new minimum sigma latitude point id. * @param maxLatPointId The new maximum sigma latitude point id. */ - void BundleResults::setSigmaLatitudeRange(Distance minLatDist, Distance maxLatDist, - QString minLatPointId, QString maxLatPointId) { - m_minSigmaLatitudeDistance = minLatDist; - m_maxSigmaLatitudeDistance = maxLatDist; - m_minSigmaLatitudePointId = minLatPointId; - m_maxSigmaLatitudePointId = maxLatPointId; + void BundleResults::setSigmaCoord1Range(Distance minCoord1Dist, Distance maxCoord1Dist, + QString minCoord1PointId, QString maxCoord1PointId) { + m_minSigmaCoord1Distance = minCoord1Dist; + m_maxSigmaCoord1Distance = maxCoord1Dist; + m_minSigmaCoord1PointId = minCoord1PointId; + m_maxSigmaCoord1PointId = maxCoord1PointId; } /** - * Sets the min and max sigma longitude distances and point ids. + * Sets the min and max sigma distances and point ids for coordinate 2. * * @param minLonDist The new minimum sigma longitude distance. * @param maxLonDist The new maximum sigma longitude distance. * @param minLonPointId The new minimum sigma longitude point id. * @param maxLonPointId The new maximum sigma longitude point id. */ - void BundleResults::setSigmaLongitudeRange(Distance minLonDist, Distance maxLonDist, - QString minLonPointId, QString maxLonPointId) { - m_minSigmaLongitudeDistance = minLonDist; - m_maxSigmaLongitudeDistance = maxLonDist; - m_minSigmaLongitudePointId = minLonPointId; - m_maxSigmaLongitudePointId = maxLonPointId; + void BundleResults::setSigmaCoord2Range(Distance minCoord2Dist, Distance maxCoord2Dist, + QString minCoord2PointId, QString maxCoord2PointId) { + m_minSigmaCoord2Distance = minCoord2Dist; + m_maxSigmaCoord2Distance = maxCoord2Dist; + m_minSigmaCoord2PointId = minCoord2PointId; + m_maxSigmaCoord2PointId = maxCoord2PointId; } /** - * Sets the min and max sigma radius distances and point ids. + * Sets the min and max sigma distances and point ids for coordinate 3. * * @param minRadDist The new minimum sigma radius distance. * @param maxRadDist The new maximum sigma radius distance. * @param minRadPointId The new minimum sigma radius point id. * @param maxRadPointId The new maximum sigma radius point id. */ - void BundleResults::setSigmaRadiusRange(Distance minRadDist, Distance maxRadDist, - QString minRadPointId, QString maxRadPointId) { - m_minSigmaRadiusDistance = minRadDist; - m_maxSigmaRadiusDistance = maxRadDist; - m_minSigmaRadiusPointId = minRadPointId; - m_maxSigmaRadiusPointId = maxRadPointId; + void BundleResults::setSigmaCoord3Range(Distance minCoord3Dist, Distance maxCoord3Dist, + QString minCoord3PointId, QString maxCoord3PointId) { + m_minSigmaCoord3Distance = minCoord3Dist; + m_maxSigmaCoord3Distance = maxCoord3Dist; + m_minSigmaCoord3PointId = minCoord3PointId; + m_maxSigmaCoord3PointId = maxCoord3PointId; } /** - * Sets the root mean square values of the adjusted latitiude sigmas, adjusted longitude sigmas, - * and adjusted radius sigmas. + * Sets the root mean square values of the adjusted sigmas for all three coordinates. * - * @param rmsFromSigmaLatStats The new RMS value of the adjusted latitude sigmas. - * @param rmsFromSigmaLonStats The new RMS value of the adjusted longitude sigmas. - * @param rmsFromSigmaRadStats The new RMS value of the adjusted radius sigmas. + * @param rmsFromSigmaCoord1Stats The new RMS value of the adjusted coord1 sigmas. + * @param rmsFromSigmaCoord2Stats The new RMS value of the adjusted coord2 sigmas. + * @param rmsFromSigmaCoord3Stats The new RMS value of the adjusted coord3 sigmas. */ - void BundleResults::setRmsFromSigmaStatistics(double rmsFromSigmaLatStats, - double rmsFromSigmaLonStats, - double rmsFromSigmaRadStats) { - m_rmsSigmaLatitudeStats = rmsFromSigmaLatStats; - m_rmsSigmaLongitudeStats = rmsFromSigmaLonStats; - m_rmsSigmaRadiusStats = rmsFromSigmaRadStats; + void BundleResults::setRmsFromSigmaStatistics( + double rmsFromSigmaCoord1Stats, + double rmsFromSigmaCoord2Stats, + double rmsFromSigmaCoord3Stats) { + m_rmsSigmaCoord1Stats = rmsFromSigmaCoord1Stats; + m_rmsSigmaCoord2Stats = rmsFromSigmaCoord2Stats; + m_rmsSigmaCoord3Stats = rmsFromSigmaCoord3Stats; } @@ -808,16 +806,6 @@ namespace Isis { } - /** - * Sets the radians to meters conversion constant for the target body. - * - * @param rtm The (double) conversion factor. - */ - void BundleResults::setRadiansToMeters(double rtm) { - m_radiansToMeters = rtm; - } - - /** * Sets if the bundle adjustment converged. * @@ -962,152 +950,152 @@ namespace Isis { /** - * Returns the minimum sigma latitude distance. + * Returns the minimum sigma distance for coordinate 1. * - * @return @b Distance The minimum sigma latitude. + * @return @b Distance The minimum sigma for Coord1. */ - Distance BundleResults::minSigmaLatitudeDistance() const { - return m_minSigmaLatitudeDistance; + Distance BundleResults::minSigmaCoord1Distance() const { + return m_minSigmaCoord1Distance; } /** - * Returns the maximum sigma latitude distance. + * Returns the maximum sigma distance for coordinate 1. * - * @return @b Distance The maximum sigma latitude. + * @return @b Distance The maximum sigma Coord1. */ - Distance BundleResults::maxSigmaLatitudeDistance() const { - return m_maxSigmaLatitudeDistance; + Distance BundleResults::maxSigmaCoord1Distance() const { + return m_maxSigmaCoord1Distance; } /** - * Returns the minimum sigma longitude distance. + * Returns the minimum sigma distance for coordinate 2. * - * @return @b Distance The minimum sigma longitude. + * @return @b Distance The minimum sigma Coord2. */ - Distance BundleResults::minSigmaLongitudeDistance() const { - return m_minSigmaLongitudeDistance; + Distance BundleResults::minSigmaCoord2Distance() const { + return m_minSigmaCoord2Distance; } /** - * Returns the maximum sigma longitude distance. + * Returns the maximum sigma distance for coordinate 2. * - * @return @b Distance The maximum sigma longitude. + * @return @b Distance The maximum sigma Coord2. */ - Distance BundleResults::maxSigmaLongitudeDistance() const { - return m_maxSigmaLongitudeDistance; + Distance BundleResults::maxSigmaCoord2Distance() const { + return m_maxSigmaCoord2Distance; } /** - * Returns the minimum sigma redius distance. + * Returns the minimum sigma distance for coordinate 3. * - * @return @b Distance The minimum sigma redius. + * @return @b Distance The minimum sigma Coord3. */ - Distance BundleResults::minSigmaRadiusDistance() const { - return m_minSigmaRadiusDistance; + Distance BundleResults::minSigmaCoord3Distance() const { + return m_minSigmaCoord3Distance; } /** - * Returns the maximum sigma redius distance. + * Returns the maximum sigma distance for coordinate 3. * - * @return @b Distance The maximum sigma radius. + * @return @b Distance The maximum sigma Coord3. */ - Distance BundleResults::maxSigmaRadiusDistance() const { - return m_maxSigmaRadiusDistance; + Distance BundleResults::maxSigmaCoord3Distance() const { + return m_maxSigmaCoord3Distance; } /** - * Returns the minimum sigma latitude point id. + * Returns the minimum sigma point id for coordinate 1. * - * @return @b @QString The minimum sigma latitude point id. + * @return @b @QString The minimum sigma Coord1 point id. */ - QString BundleResults::minSigmaLatitudePointId() const { - return m_minSigmaLatitudePointId; + QString BundleResults::minSigmaCoord1PointId() const { + return m_minSigmaCoord1PointId; } /** - * Returns the maximum sigma latitude point id. + * Returns the maximum sigma point id for coordinate 1. * - * @return @b @QString The maximum sigma latitude point id. + * @return @b @QString The maximum sigma Coord1 point id. */ - QString BundleResults::maxSigmaLatitudePointId() const { - return m_maxSigmaLatitudePointId; + QString BundleResults::maxSigmaCoord1PointId() const { + return m_maxSigmaCoord1PointId; } /** - * Returns the minimum sigma longitude point id. + * Returns the minimum sigma point id for coordinate 2. * * @return @b @QString The minimum sigma longitude point id. */ - QString BundleResults::minSigmaLongitudePointId() const { - return m_minSigmaLongitudePointId; + QString BundleResults::minSigmaCoord2PointId() const { + return m_minSigmaCoord2PointId; } /** - * Returns the maximum sigma longitude point id. + * Returns the maximum sigma point id for coordinate 2. * - * @return @b @QString The maximum sigma longitude point id. + * @return @b @QString The maximum sigma Coord2 point id. */ - QString BundleResults::maxSigmaLongitudePointId() const { - return m_maxSigmaLongitudePointId; + QString BundleResults::maxSigmaCoord2PointId() const { + return m_maxSigmaCoord2PointId; } /** - * Returns the minimum sigma radius point id. + * Returns the minimum sigma point id for coordinate 3. * - * @return @b @QString The minimum sigma radius point id. + * @return @b @QString The minimum sigma Coord3 point id. */ - QString BundleResults::minSigmaRadiusPointId() const { - return m_minSigmaRadiusPointId; + QString BundleResults::minSigmaCoord3PointId() const { + return m_minSigmaCoord3PointId; } /** - * Returns the maximum sigma radius point id. + * Returns the maximum sigma point id for coordinate 3. * - * @return @b @QString The maximum sigma radius point id. + * @return @b @QString The maximum sigma Coord3 point id. */ - QString BundleResults::maxSigmaRadiusPointId() const { - return m_maxSigmaRadiusPointId; + QString BundleResults::maxSigmaCoord3PointId() const { + return m_maxSigmaCoord3PointId; } /** - * Returns the RMS of the adjusted latitude sigmas. + * Returns the RMS of the adjusted sigmas for coordinate 1. * - * @return @b double The RMS of the adjusted latitude sigmas. + * @return @b double The RMS of the adjusted Coord1 sigmas. */ - double BundleResults::sigmaLatitudeStatisticsRms() const { - return m_rmsSigmaLatitudeStats; + double BundleResults::sigmaCoord1StatisticsRms() const { + return m_rmsSigmaCoord1Stats; } /** - * Returns the RMS of the adjusted longitude sigmas. + * Returns the RMS of the adjusted sigmas for coordinate 2. * - * @return @b double The RMS of the adjusted longitude sigmas. + * @return @b double The RMS of the adjusted Coord2 sigmas. */ - double BundleResults::sigmaLongitudeStatisticsRms() const { - return m_rmsSigmaLongitudeStats; + double BundleResults::sigmaCoord2StatisticsRms() const { + return m_rmsSigmaCoord2Stats; } /** - * Returns the RMS of the adjusted raidus sigmas. + * Returns the RMS of the adjusted sigmas for coordinate 3. * - * @return @b double The RMS of the adjusted radius sigmas. + * @return @b double The RMS of the adjusted Coord3 sigmas. */ - double BundleResults::sigmaRadiusStatisticsRms() const { - return m_rmsSigmaRadiusStats; + double BundleResults::sigmaCoord3StatisticsRms() const { + return m_rmsSigmaCoord3Stats; } @@ -1151,16 +1139,6 @@ namespace Isis { } - /** - * Returns the radians to meters conversion factor for the target body. - * - * @return @b double The conversion factor. - */ - double BundleResults::radiansToMeters() const { - return m_radiansToMeters; - } - - /** * Returns the number of observation that were rejected. * @@ -1450,6 +1428,18 @@ namespace Isis { } + SurfacePoint::CoordinateType BundleResults::coordTypeReports() { + // Get the coordinate type from the output net if it exists. Otherwise use the default. + SurfacePoint::CoordinateType type = SurfacePoint::Latitudinal; + + if (m_outNet) { + type = outputControlNet()->GetCoordType(); + } + + return type; + } + + /** * Saves the BundleResults object to an XML file. * @@ -1457,6 +1447,13 @@ namespace Isis { * @param project The project that the BundleResults object belongs to. */ void BundleResults::save(QXmlStreamWriter &stream, const Project *project) const { + // Get the coordinate type from the output net if it exists. Otherwise use the default. + SurfacePoint::CoordinateType coordType = SurfacePoint::Latitudinal; + + if (m_outNet) { + coordType = outputControlNet()->GetCoordType(); + } + stream.writeStartElement("bundleResults"); stream.writeStartElement("correlationMatrix"); stream.writeAttribute("correlationFileName", @@ -1506,9 +1503,23 @@ namespace Isis { stream.writeAttribute("xy", toString(rmsRxy())); stream.writeEndElement(); // end residuals element stream.writeStartElement("sigmas"); - stream.writeAttribute("lat", toString(sigmaLatitudeStatisticsRms())); - stream.writeAttribute("lon", toString(sigmaLongitudeStatisticsRms())); - stream.writeAttribute("rad", toString(sigmaRadiusStatisticsRms())); + + // Set the label based of the coordinate type set for reports + switch (coordType) { + case SurfacePoint::Latitudinal: + stream.writeAttribute("lat", toString(sigmaCoord1StatisticsRms())); + stream.writeAttribute("lon", toString(sigmaCoord2StatisticsRms())); + stream.writeAttribute("rad", toString(sigmaCoord3StatisticsRms())); + break; + case SurfacePoint::Rectangular: + stream.writeAttribute("x", toString(sigmaCoord1StatisticsRms())); + stream.writeAttribute("y", toString(sigmaCoord2StatisticsRms())); + stream.writeAttribute("z", toString(sigmaCoord3StatisticsRms())); + break; + default: + IString msg ="Unknown surface point coordinate type enum [" + toString(coordType) + "]." ; + throw IException(IException::Programmer, msg, _FILEINFO_); + } stream.writeEndElement(); // end sigmas element stream.writeStartElement("imageResidualsLists"); @@ -1603,30 +1614,65 @@ namespace Isis { stream.writeEndElement(); // end elapsed time stream.writeStartElement("minMaxSigmas"); - stream.writeStartElement("minLat"); - stream.writeAttribute("value", toString(minSigmaLatitudeDistance().meters())); - stream.writeAttribute("pointId", minSigmaLatitudePointId()); - stream.writeEndElement(); - stream.writeStartElement("maxLat"); - stream.writeAttribute("value", toString(maxSigmaLatitudeDistance().meters())); - stream.writeAttribute("pointId", maxSigmaLatitudePointId()); - stream.writeEndElement(); - stream.writeStartElement("minLon"); - stream.writeAttribute("value", toString(minSigmaLongitudeDistance().meters())); - stream.writeAttribute("pointId", minSigmaLongitudePointId()); - stream.writeEndElement(); - stream.writeStartElement("maxLon"); - stream.writeAttribute("value", toString(maxSigmaLongitudeDistance().meters())); - stream.writeAttribute("pointId", maxSigmaLongitudePointId()); - stream.writeEndElement(); - stream.writeStartElement("minRad"); - stream.writeAttribute("value", toString(minSigmaRadiusDistance().meters())); - stream.writeAttribute("pointId", minSigmaRadiusPointId()); - stream.writeEndElement(); - stream.writeStartElement("maxRad"); - stream.writeAttribute("value", toString(maxSigmaRadiusDistance().meters())); - stream.writeAttribute("pointId", maxSigmaRadiusPointId()); - stream.writeEndElement(); + + // Write the labels corresponding to the coordinate type set for reports + switch (coordType) { + case SurfacePoint::Latitudinal: + stream.writeStartElement("minLat"); + stream.writeAttribute("value", toString(minSigmaCoord1Distance().meters())); + stream.writeAttribute("pointId", minSigmaCoord1PointId()); + stream.writeEndElement(); + stream.writeStartElement("maxLat"); + stream.writeAttribute("value", toString(maxSigmaCoord1Distance().meters())); + stream.writeAttribute("pointId", maxSigmaCoord1PointId()); + stream.writeEndElement(); + stream.writeStartElement("minLon"); + stream.writeAttribute("value", toString(minSigmaCoord2Distance().meters())); + stream.writeAttribute("pointId", minSigmaCoord2PointId()); + stream.writeEndElement(); + stream.writeStartElement("maxLon"); + stream.writeAttribute("value", toString(maxSigmaCoord2Distance().meters())); + stream.writeAttribute("pointId", maxSigmaCoord2PointId()); + stream.writeEndElement(); + stream.writeStartElement("minRad"); + stream.writeAttribute("value", toString(minSigmaCoord3Distance().meters())); + stream.writeAttribute("pointId", minSigmaCoord3PointId()); + stream.writeEndElement(); + stream.writeStartElement("maxRad"); + stream.writeAttribute("value", toString(maxSigmaCoord3Distance().meters())); + stream.writeAttribute("pointId", maxSigmaCoord3PointId()); + stream.writeEndElement(); + break; + case SurfacePoint::Rectangular: + stream.writeStartElement("minX"); + stream.writeAttribute("value", toString(minSigmaCoord1Distance().meters())); + stream.writeAttribute("pointId", minSigmaCoord1PointId()); + stream.writeEndElement(); + stream.writeStartElement("maxX"); + stream.writeAttribute("value", toString(maxSigmaCoord1Distance().meters())); + stream.writeAttribute("pointId", maxSigmaCoord1PointId()); + stream.writeEndElement(); + stream.writeStartElement("minY"); + stream.writeAttribute("value", toString(minSigmaCoord2Distance().meters())); + stream.writeAttribute("pointId", minSigmaCoord2PointId()); + stream.writeEndElement(); + stream.writeStartElement("maxY"); + stream.writeAttribute("value", toString(maxSigmaCoord2Distance().meters())); + stream.writeAttribute("pointId", maxSigmaCoord2PointId()); + stream.writeEndElement(); + stream.writeStartElement("minZ"); + stream.writeAttribute("value", toString(minSigmaCoord3Distance().meters())); + stream.writeAttribute("pointId", minSigmaCoord3PointId()); + stream.writeEndElement(); + stream.writeStartElement("maxZ"); + stream.writeAttribute("value", toString(maxSigmaCoord3Distance().meters())); + stream.writeAttribute("pointId", maxSigmaCoord3PointId()); + stream.writeEndElement(); + break; + default: + IString msg ="Unknown surface point coordinate type enum [" + toString(coordType) + "]." ; + throw IException(IException::Programmer, msg, _FILEINFO_); + } stream.writeEndElement(); // end minMaxSigmas // call max likelihood setup from startElement to fill the rest of these values... @@ -1764,17 +1810,27 @@ namespace Isis { else if (qName == "sigmas") { QString lat = atts.value("lat"); if (!lat.isEmpty()) { - m_xmlHandlerBundleResults->m_rmsSigmaLatitudeStats = toDouble(lat); + m_xmlHandlerBundleResults->m_rmsSigmaCoord1Stats = toDouble(lat); } - QString lon = atts.value("lon"); if (!lon.isEmpty()) { - m_xmlHandlerBundleResults->m_rmsSigmaLongitudeStats = toDouble(lon); + m_xmlHandlerBundleResults->m_rmsSigmaCoord2Stats = toDouble(lon); } - QString rad = atts.value("rad"); if (!rad.isEmpty()) { - m_xmlHandlerBundleResults->m_rmsSigmaRadiusStats = toDouble(rad); + m_xmlHandlerBundleResults->m_rmsSigmaCoord3Stats = toDouble(rad); + } + QString x = atts.value("x"); + if (!x.isEmpty()) { + m_xmlHandlerBundleResults->m_rmsSigmaCoord1Stats = toDouble(x); + } + QString y = atts.value("y"); + if (!y.isEmpty()) { + m_xmlHandlerBundleResults->m_rmsSigmaCoord2Stats = toDouble(y); + } + QString z = atts.value("z"); + if (!z.isEmpty()) { + m_xmlHandlerBundleResults->m_rmsSigmaCoord3Stats = toDouble(z); } } else if (qName == "residualsList") { @@ -1860,68 +1916,153 @@ namespace Isis { else if (qName == "minLat") { QString minLat = atts.value("value"); if (!minLat.isEmpty()) { - m_xmlHandlerBundleResults->m_minSigmaLatitudeDistance.setMeters(toDouble(minLat)); + m_xmlHandlerBundleResults->m_minSigmaCoord1Distance.setMeters(toDouble(minLat)); } QString minLatPointId = atts.value("pointId"); if (!minLatPointId.isEmpty()) { - m_xmlHandlerBundleResults->m_minSigmaLatitudePointId = minLatPointId; + m_xmlHandlerBundleResults->m_minSigmaCoord1PointId = minLatPointId; + } + + } + else if (qName == "minX") { + QString minX = atts.value("value"); + if (!minX.isEmpty()) { + m_xmlHandlerBundleResults->m_minSigmaCoord1Distance.setMeters(toDouble(minX)); + } + + QString minXPointId = atts.value("pointId"); + if (!minXPointId.isEmpty()) { + m_xmlHandlerBundleResults->m_minSigmaCoord1PointId = minXPointId; } } else if (qName == "maxLat") { QString maxLat = atts.value("value"); if (!maxLat.isEmpty()) { - m_xmlHandlerBundleResults->m_maxSigmaLatitudeDistance.setMeters(toDouble(maxLat)); + m_xmlHandlerBundleResults->m_maxSigmaCoord1Distance.setMeters(toDouble(maxLat)); } QString maxLatPointId = atts.value("pointId"); if (!maxLatPointId.isEmpty()) { - m_xmlHandlerBundleResults->m_maxSigmaLatitudePointId = maxLatPointId; + m_xmlHandlerBundleResults->m_maxSigmaCoord1PointId = maxLatPointId; } + + } + else if (qName == "maxX") { + + QString maxX = atts.value("value"); + if (!maxX.isEmpty()) { + m_xmlHandlerBundleResults->m_maxSigmaCoord1Distance.setMeters(toDouble(maxX)); + } + + QString maxXPointId = atts.value("pointId"); + if (!maxXPointId.isEmpty()) { + m_xmlHandlerBundleResults->m_maxSigmaCoord1PointId = maxXPointId; + } + } else if (qName == "minLon") { + QString minLon = atts.value("value"); if (!minLon.isEmpty()) { - m_xmlHandlerBundleResults->m_minSigmaLongitudeDistance.setMeters(toDouble(minLon)); + m_xmlHandlerBundleResults->m_minSigmaCoord2Distance.setMeters(toDouble(minLon)); } QString minLonPointId = atts.value("pointId"); if (!minLonPointId.isEmpty()) { - m_xmlHandlerBundleResults->m_minSigmaLongitudePointId = minLonPointId; + m_xmlHandlerBundleResults->m_minSigmaCoord2PointId = minLonPointId; + } + + } + else if (qName == "minY") { + + QString minY = atts.value("value"); + if (!minY.isEmpty()) { + m_xmlHandlerBundleResults->m_minSigmaCoord2Distance.setMeters(toDouble(minY)); + } + + QString minYPointId = atts.value("pointId"); + if (!minYPointId.isEmpty()) { + m_xmlHandlerBundleResults->m_minSigmaCoord2PointId = minYPointId; } + } else if (qName == "maxLon") { + QString maxLon = atts.value("value"); if (!maxLon.isEmpty()) { - m_xmlHandlerBundleResults->m_maxSigmaLongitudeDistance.setMeters(toDouble(maxLon)); + m_xmlHandlerBundleResults->m_maxSigmaCoord2Distance.setMeters(toDouble(maxLon)); } QString maxLonPointId = atts.value("pointId"); if (!maxLonPointId.isEmpty()) { - m_xmlHandlerBundleResults->m_maxSigmaLongitudePointId = maxLonPointId; + m_xmlHandlerBundleResults->m_maxSigmaCoord2PointId = maxLonPointId; + } + + } + else if (qName == "maxY") { + QString maxY = atts.value("value"); + if (!maxY.isEmpty()) { + m_xmlHandlerBundleResults->m_maxSigmaCoord2Distance.setMeters(toDouble(maxY)); + } + + QString maxYPointId = atts.value("pointId"); + if (!maxYPointId.isEmpty()) { + m_xmlHandlerBundleResults->m_maxSigmaCoord2PointId = maxYPointId; } + } else if (qName == "minRad") { + QString minRad = atts.value("value"); if (!minRad.isEmpty()) { - m_xmlHandlerBundleResults->m_minSigmaRadiusDistance.setMeters(toDouble(minRad)); + m_xmlHandlerBundleResults->m_minSigmaCoord3Distance.setMeters(toDouble(minRad)); } QString minRadPointId = atts.value("pointId"); if (!minRadPointId.isEmpty()) { - m_xmlHandlerBundleResults->m_minSigmaRadiusPointId = minRadPointId; + m_xmlHandlerBundleResults->m_minSigmaCoord3PointId = minRadPointId; + } + + } + else if (qName == "minZ") { + + QString minZ = atts.value("value"); + if (!minZ.isEmpty()) { + m_xmlHandlerBundleResults->m_minSigmaCoord3Distance.setMeters(toDouble(minZ)); + } + + QString minZPointId = atts.value("pointId"); + if (!minZPointId.isEmpty()) { + m_xmlHandlerBundleResults->m_minSigmaCoord3PointId = minZPointId; } + } else if (qName == "maxRad") { + QString maxRad = atts.value("value"); if (!maxRad.isEmpty()) { - m_xmlHandlerBundleResults->m_maxSigmaRadiusDistance.setMeters(toDouble(maxRad)); + m_xmlHandlerBundleResults->m_maxSigmaCoord3Distance.setMeters(toDouble(maxRad)); } QString maxRadPointId = atts.value("pointId"); if (!maxRadPointId.isEmpty()) { - m_xmlHandlerBundleResults->m_maxSigmaRadiusPointId = maxRadPointId; + m_xmlHandlerBundleResults->m_maxSigmaCoord3PointId = maxRadPointId; } + + } + else if (qName == "maxZ") { + + QString maxZ = atts.value("value"); + if (!maxZ.isEmpty()) { + m_xmlHandlerBundleResults->m_maxSigmaCoord3Distance.setMeters(toDouble(maxZ)); + } + + QString maxZPointId = atts.value("pointId"); + if (!maxZPointId.isEmpty()) { + m_xmlHandlerBundleResults->m_maxSigmaCoord3PointId = maxZPointId; + } + } else if (qName == "maximumLikelihoodEstimation") { QString maximumLikelihoodIndex = atts.value("maximumLikelihoodIndex"); diff --git a/isis/src/control/objs/BundleResults/BundleResults.h b/isis/src/control/objs/BundleResults/BundleResults.h index 2aa943e0f7659766c434be486ef8ddff46078a7c..3fd2b27e0d44521cff2bd937b00a9770308b87ab 100644 --- a/isis/src/control/objs/BundleResults/BundleResults.h +++ b/isis/src/control/objs/BundleResults/BundleResults.h @@ -39,6 +39,7 @@ #include "MaximumLikelihoodWFunctions.h" #include "PvlObject.h" #include "Statistics.h" // ??? +#include "SurfacePoint.h" #include "XmlStackedHandler.h" // Qt Library @@ -84,6 +85,13 @@ namespace Isis { * @history 2017-04-24 Ian Humphrey - Removed pvlObject() method. Commented out m_id serialization * for save() (causes segfault in unit test for empty xml). Fixes #4797. * @history 2017-04-27 J Bonn - Updated serialization code and tests. + * @history 2017-05-30 Debbie A. Cook - Corrected class names in method comments and generalized + * control point coordinate names. Methods changed: copy constructor, + * assignment operator, initialize, Also added access methods for coordinate types. + * References #4649 and #501. + * @history 2018-09-30 Debbie A. Cook - Removed methods setRadiansToMeters and + * radiansToMeters and member variable m_radiansToMeters. References #4649 + * and #501. */ class BundleResults : public QObject { Q_OBJECT @@ -104,15 +112,15 @@ namespace Isis { void setRmsImageResidualLists(QVector rmsImageLineResiduals, QVector rmsImageSampleResiduals, QVector rmsImageResiduals); - void setSigmaLatitudeRange(Distance minLatDist, Distance maxLatDist, - QString minLatPointId, QString maxLatPointId); - void setSigmaLongitudeRange(Distance minLonDist, Distance maxLonDist, - QString minLonPointId, QString maxLonPointId); - void setSigmaRadiusRange(Distance minRadDist, Distance maxRadDist, - QString minRadPointId, QString maxRadPointId); - void setRmsFromSigmaStatistics(double rmsFromSigmaLatStats, - double rmsFromSigmaLonStats, - double rmsFromSigmaRadStats); + void setSigmaCoord1Range(Distance minCoord1Dist, Distance maxCoord1Dist, + QString minCoord1PointId, QString maxCoord1PointId); + void setSigmaCoord2Range(Distance minCoord2Dist, Distance maxCoord2Dist, + QString minCoord2PointId, QString maxCoord2PointId); + void setSigmaCoord3Range(Distance minCoord3Dist, Distance maxCoord3Dist, + QString minCoord3PointId, QString maxCoord3PointId); + void setRmsFromSigmaStatistics(double rmsFromSigmaCoord1Stats, + double rmsFromSigmaCoord2Stats, + double rmsFromSigmaCoord3Stats); void maximumLikelihoodSetUp( QList< QPair< MaximumLikelihoodWFunctions::Model, double > > modelsWithQuantiles); void printMaximumLikelihoodTierInformation(); @@ -165,7 +173,6 @@ namespace Isis { void setSigma0(double sigma0); void setElapsedTime(double time); void setElapsedTimeErrorProp(double time); - void setRadiansToMeters(double rtm); void setConverged(bool converged); // or initialze method void setBundleControlPoints(QVector controlPoints); void setOutputControlNet(ControlNetQsp outNet); @@ -182,26 +189,30 @@ namespace Isis { QVector rmsImageRASigmas() const; // currently unused ??? QVector rmsImageDECSigmas() const; // currently unused ??? QVector rmsImageTWISTSigmas() const; // currently unused ??? - Distance minSigmaLatitudeDistance() const; - Distance maxSigmaLatitudeDistance() const; - Distance minSigmaLongitudeDistance() const; - Distance maxSigmaLongitudeDistance() const; - Distance minSigmaRadiusDistance() const; - Distance maxSigmaRadiusDistance() const; - QString maxSigmaLatitudePointId() const; - QString minSigmaLatitudePointId() const; - QString minSigmaLongitudePointId() const; - QString maxSigmaLongitudePointId() const; - QString minSigmaRadiusPointId() const; - QString maxSigmaRadiusPointId() const; - double sigmaLatitudeStatisticsRms() const; - double sigmaLongitudeStatisticsRms() const; - double sigmaRadiusStatisticsRms() const; + // *** TODO *** Will we ever want to request a specific coordinate type? + // (Lat or X) or just whatever is the designated type? + SurfacePoint::CoordinateType coordTypeReports(); + + Distance minSigmaCoord1Distance() const; + Distance maxSigmaCoord1Distance() const; + Distance minSigmaCoord2Distance() const; + Distance maxSigmaCoord2Distance() const; + Distance minSigmaCoord3Distance() const; + Distance maxSigmaCoord3Distance() const; + QString maxSigmaCoord1PointId() const; + QString minSigmaCoord1PointId() const; + QString minSigmaCoord2PointId() const; + QString maxSigmaCoord2PointId() const; + QString minSigmaCoord3PointId() const; + QString maxSigmaCoord3PointId() const; + double sigmaCoord1StatisticsRms() const; + double sigmaCoord2StatisticsRms() const; + double sigmaCoord3StatisticsRms() const; + double rmsRx() const; // currently unused ??? double rmsRy() const; // currently unused ??? double rmsRxy() const; // currently unused ??? double rejectionLimit() const; - double radiansToMeters() const; int numberRejectedObservations() const; int numberObservations() const; @@ -289,7 +300,6 @@ namespace Isis { CorrelationMatrix *m_correlationMatrix; //!< The correlation matrix from the BundleAdjust. - int m_numberFixedPoints; //!< number of 'fixed' (ground) points (define) // Currently set but unused int m_numberIgnoredPoints; //!< number of ignored points @@ -313,11 +323,10 @@ namespace Isis { double m_sigma0; //!< std deviation of unit weight double m_elapsedTime; //!< elapsed time for bundle double m_elapsedTimeErrorProp; //!< elapsed time for error propagation - double m_radiansToMeters; //!< radian to meters conversion factor for the body bool m_converged; - + // Variables for output methods in BundleSolutionInfo - + QVector m_bundleControlPoints; /**< The vector of BundleControlPoints from BundleAdjust. Equivalent to the output control net minus @@ -358,23 +367,23 @@ namespace Isis { //!< The root mean square image twist sigmas. QVector m_rmsImageTWISTSigmas; // unset and unused ??? - Distance m_minSigmaLatitudeDistance; //!< The minimum sigma latitude distance. - Distance m_maxSigmaLatitudeDistance; //!< The maximum sigma latitude distance. - Distance m_minSigmaLongitudeDistance; //!< The minimum sigma longitude distance. - Distance m_maxSigmaLongitudeDistance; //!< The maximum sigma longitude distance. - Distance m_minSigmaRadiusDistance; //!< The minimum sigma radius distance. - Distance m_maxSigmaRadiusDistance; //!< The maximum sigma radius distance. - - QString m_minSigmaLatitudePointId; //!< The minimum sigma latitude point id. - QString m_maxSigmaLatitudePointId; //!< The maximum sigma latitude point id. - QString m_minSigmaLongitudePointId; //!< The minimum sigma longitude point id. - QString m_maxSigmaLongitudePointId; //!< The maximum sigma longitude point id. - QString m_minSigmaRadiusPointId; //!< The minimum sigma radius point id. - QString m_maxSigmaRadiusPointId; //!< The maximum sigma radius point id. - - double m_rmsSigmaLatitudeStats; //!< rms of adjusted Latitude sigmas - double m_rmsSigmaLongitudeStats; //!< rms of adjusted Longitude sigmas - double m_rmsSigmaRadiusStats; //!< rms of adjusted Radius sigmas + Distance m_minSigmaCoord1Distance; //!< The minimum sigma latitude distance. + Distance m_maxSigmaCoord1Distance; //!< The maximum sigma latitude distance. + Distance m_minSigmaCoord2Distance; //!< The minimum sigma longitude distance. + Distance m_maxSigmaCoord2Distance; //!< The maximum sigma longitude distance. + Distance m_minSigmaCoord3Distance; //!< The minimum sigma radius distance. + Distance m_maxSigmaCoord3Distance; //!< The maximum sigma radius distance. + + QString m_minSigmaCoord1PointId; //!< The minimum sigma coordinate 1 point id. + QString m_maxSigmaCoord1PointId; //!< The maximum sigma coordinate 1 point id. + QString m_minSigmaCoord2PointId; //!< The minimum sigma coordinate 2 point id. + QString m_maxSigmaCoord2PointId; //!< The maximum sigma coordinate2 point id. + QString m_minSigmaCoord3PointId; //!< The minimum sigma coordinate 3 point id. + QString m_maxSigmaCoord3PointId; //!< The maximum sigma coordinate 3 point id. + + double m_rmsSigmaCoord1Stats; //!< rms of adjusted Latitude sigmas + double m_rmsSigmaCoord2Stats; //!< rms of adjusted Longitude sigmas + double m_rmsSigmaCoord3Stats; //!< rms of adjusted Radius sigmas //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // variables for maximum likelihood estimation diff --git a/isis/src/control/objs/BundleResults/BundleResults.truth b/isis/src/control/objs/BundleResults/BundleResults.truth index bd039dce5fadf9d7efb56ba710de65c385db6c5b..35d9aba939258c8a5776d0b5467485b7f2e3beb6 100644 --- a/isis/src/control/objs/BundleResults/BundleResults.truth +++ b/isis/src/control/objs/BundleResults/BundleResults.truth @@ -429,7 +429,142 @@ Testing XML: Object deserialized as (should match object above): +Testing rectangular coordinate type in control net and settings + +bundle control points... + FreePoint FREE 1 of 1 3.54 Null Null Null N/A N/A N/A + + FixedPoint FIXED 0 of 0 0.00 -0.00000000 0.00000000 0.01000000 N/A N/A N/A + + +Testing XML serialization for a rectangular net 1: round trip serialization of fully populated BundleSettings object... +Serializing test XML object to file... + + + + + + param1 + param2 + + + param3 + param4 + param5 + + + + + 1 + 1 + 1 + 7.0 + 8 + 9 + 10 + 11 + 10 + 2 + 32 + 0 + 0.0 + Yes + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Testing rectangular XML: reading serialized BundleResults back in... +Testing rectangular XML: Object deserialized as (should match object above): + + + + + + param1 + param2 + + + param3 + param4 + param5 + + + + + 1 + 1 + 1 + 7.0 + 8 + 9 + 10 + 11 + 10 + 2 + 32 + 0 + 0.0 + Yes + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Testing error throws... **I/O ERROR** Computed degrees of freedom [-1] is invalid. **I/O ERROR** Computed degrees of freedom [0] is invalid. **PROGRAMMER ERROR** Output Control Network has not been set. +**PROGRAMMER ERROR** Unknown surface point coordinate type enum [-1]. diff --git a/isis/src/control/objs/BundleResults/unitTest.cpp b/isis/src/control/objs/BundleResults/unitTest.cpp index 79a99c157511a6bbfb5dc13e060bfc1df897f423..3c45479843ae3f3664dcb8671e8820577d9bd7b2 100755 --- a/isis/src/control/objs/BundleResults/unitTest.cpp +++ b/isis/src/control/objs/BundleResults/unitTest.cpp @@ -157,15 +157,16 @@ int main(int argc, char *argv[]) { results.setRmsImageResidualLists(rmsImageLineResiduals, rmsImageSampleResiduals, rmsImageResiduals); - results.setSigmaLatitudeRange(Distance(0.5, Distance::Meters), + results.setSigmaCoord1Range(Distance(0.5, Distance::Meters), Distance(89.6, Distance::Meters), "MinLatId", "MaxLatId"); - results.setSigmaLongitudeRange(Distance(0.7, Distance::Meters), + results.setSigmaCoord2Range(Distance(0.7, Distance::Meters), Distance(179.2, Distance::Meters), "MinLonId", "MaxLonId"); - results.setSigmaRadiusRange(Distance(0.9, Distance::Meters), + results.setSigmaCoord3Range(Distance(0.9, Distance::Meters), Distance(354.4, Distance::Meters), "MinRadId", "MaxRadId"); + results.setRmsFromSigmaStatistics(0.123, 0.456, 0.789); results.setRmsXYResiduals(4.0, 5.0, 6.0); results.setRejectionLimit(7.0); @@ -187,7 +188,6 @@ int main(int argc, char *argv[]) { results.incrementFixedPoints(); results.incrementHeldImages(); results.incrementIgnoredPoints(); - results.setRadiansToMeters(23.68); results.setIterations(6); printXml(results); qDebug() << ""; @@ -207,6 +207,7 @@ int main(int argc, char *argv[]) { imgsAndParams.insert("img1", list1); imgsAndParams.insert("img2", list2); results.setCorrMatImgsAndParams(imgsAndParams); + copyResults = results; qDebug() << ""; qDebug() << "Testing storage for output methods..."; @@ -230,8 +231,11 @@ int main(int argc, char *argv[]) { ControlNet outNet; outNet.AddPoint(freePoint); outNet.AddPoint(fixedPoint); - BundleControlPointQsp freeBundleControlPoint(new BundleControlPoint(freePoint)); - BundleControlPointQsp fixedBundleControlPoint(new BundleControlPoint(fixedPoint)); + BundleSettingsQsp settings = BundleSettingsQsp(new BundleSettings()); + BundleControlPointQsp freeBundleControlPoint( + new BundleControlPoint(settings, freePoint)); + BundleControlPointQsp fixedBundleControlPoint( + new BundleControlPoint(settings, fixedPoint)); QVector bundleControlPointVector; bundleControlPointVector.append(freeBundleControlPoint); bundleControlPointVector.append(fixedBundleControlPoint); @@ -310,6 +314,58 @@ int main(int argc, char *argv[]) { printXml(bsFromXml); + qDebug() << "Testing rectangular coordinate type in control net and settings"; + settings->setSolveOptions(false, false, false, false, SurfacePoint::Rectangular, + SurfacePoint::Rectangular); + // outNetRect.SetCoordType(SurfacePoint::Rectangular); + outNet.SetCoordType(SurfacePoint::Rectangular); + BundleControlPointQsp freeRBundleControlPoint( + new BundleControlPoint(settings, freePoint)); + BundleControlPointQsp fixedRBundleControlPoint( + new BundleControlPoint(settings, fixedPoint)); + QVector bundleControlPointVectorR; + bundleControlPointVectorR.append(freeRBundleControlPoint); + bundleControlPointVectorR.append(fixedRBundleControlPoint); + copyResults.setBundleControlPoints(bundleControlPointVectorR); + copyResults.setOutputControlNet(ControlNetQsp(new ControlNet(outNet))); + copyResults.setObservations(observationVector); + qDebug() << ""; + + qDebug() << "bundle control points..."; + accessedControlPoints = copyResults.bundleControlPoints(); + for (int i = 0; i < accessedControlPoints.size(); i++) { + qDebug().noquote() << accessedControlPoints[i]->formatBundleOutputSummaryString(false); + } + + qDebug() << ""; + + qDebug() << "Testing XML serialization for a rectangular net 1: round trip serialization of fully populated BundleSettings object..."; + qDebug() << "Serializing test XML object to file..."; + printXml(copyResults); + FileName xmlFileR("./BundleResultsR.xml"); + xmlPath = xmlFileR.expanded(); + QFile qXmlFileR(xmlPath); + if (!qXmlFileR.open(QIODevice::WriteOnly|QIODevice::Text)) { + throw IException(IException::Io, + QString("Unable to open xml file, [%1], with write access").arg(xmlPath), + _FILEINFO_); + } + QXmlStreamWriter writerR(&qXmlFileR); + writerR.setAutoFormatting(true); + writerR.writeStartDocument(); + project = NULL; + copyResults.save(writerR, project); + writerR.writeEndDocument(); + qXmlFileR.close(); + + qDebug() << "Testing rectangular XML: reading serialized BundleResults back in..."; + BundleResultsXmlHandlerTester bsRectFromXml(project, &reader, xmlFileR); + // Set the output control net in bsRectFromXml in order to get the desired coordinate type + bsRectFromXml.setOutputControlNet(ControlNetQsp(new ControlNet(outNet))); + qDebug() << "Testing rectangular XML: Object deserialized as (should match object above):"; + printXml(bsRectFromXml); + + qDebug() << "Testing error throws..."; try { results.setNumberObservations(0); @@ -334,8 +390,16 @@ int main(int argc, char *argv[]) { e.print(); } try { - BundleResults defaultResaults; - defaultResaults.outputControlNet(); + BundleResults defaultResults; + defaultResults.outputControlNet(); + } + catch (IException &e) { + e.print(); + } + try { + outNet.SetCoordType(SurfacePoint::CoordinateType (-1)); + results.setOutputControlNet(ControlNetQsp(new ControlNet(outNet))); + printXml(results); } catch (IException &e) { e.print(); diff --git a/isis/src/control/objs/BundleSettings/BundleSettings.cpp b/isis/src/control/objs/BundleSettings/BundleSettings.cpp index 305aead1d942e6a2470ae396f1947e3b3c7bdb25..fb7cd9a615ccc5ba37ca94c38318ed77f9c205f6 100644 --- a/isis/src/control/objs/BundleSettings/BundleSettings.cpp +++ b/isis/src/control/objs/BundleSettings/BundleSettings.cpp @@ -54,9 +54,10 @@ namespace Isis { m_outlierRejectionMultiplier = 3.0; // Parameter Uncertainties (Weighting) - m_globalLatitudeAprioriSigma = Isis::Null; - m_globalLongitudeAprioriSigma = Isis::Null; - m_globalRadiusAprioriSigma = Isis::Null; + // The units are meters for either coordinate type + m_globalPointCoord1AprioriSigma = Isis::Null; + m_globalPointCoord2AprioriSigma = Isis::Null; + m_globalPointCoord3AprioriSigma = Isis::Null; // Convergence Criteria m_convergenceCriteria = BundleSettings::Sigma0; @@ -75,6 +76,10 @@ namespace Isis { // m_solveTargetBodyRotationRate = false; // m_solveTargetBodyRadiusMethod = None; + // Control Points + m_cpCoordTypeReports = SurfacePoint::Latitudinal; + m_cpCoordTypeBundle = SurfacePoint::Latitudinal; + // Output Options m_outputFilePrefix = ""; } @@ -119,9 +124,9 @@ namespace Isis { m_createInverseMatrix(other.m_createInverseMatrix), m_outlierRejection(other.m_outlierRejection), m_outlierRejectionMultiplier(other.m_outlierRejectionMultiplier), - m_globalLatitudeAprioriSigma(other.m_globalLatitudeAprioriSigma), - m_globalLongitudeAprioriSigma(other.m_globalLongitudeAprioriSigma), - m_globalRadiusAprioriSigma(other.m_globalRadiusAprioriSigma), + m_globalPointCoord1AprioriSigma(other.m_globalPointCoord1AprioriSigma), + m_globalPointCoord2AprioriSigma(other.m_globalPointCoord2AprioriSigma), + m_globalPointCoord3AprioriSigma(other.m_globalPointCoord3AprioriSigma), m_observationSolveSettings(other.m_observationSolveSettings), m_convergenceCriteria(other.m_convergenceCriteria), m_convergenceCriteriaThreshold(other.m_convergenceCriteriaThreshold), @@ -129,6 +134,8 @@ namespace Isis { m_maximumLikelihood(other.m_maximumLikelihood), m_solveTargetBody(other.m_solveTargetBody), m_bundleTargetBody(other.m_bundleTargetBody), + m_cpCoordTypeReports(other.m_cpCoordTypeReports), + m_cpCoordTypeBundle(other.m_cpCoordTypeBundle), m_outputFilePrefix(other.m_outputFilePrefix){ } @@ -147,6 +154,10 @@ namespace Isis { * @param other The BundleSettings object to be copied. * * @return @b BundleSettings& A reference to the copied BundleSettings object. + * + * @internal + * @history 2017-07-04 Debbie A. Cook - Added new coordType members and made + * global coordinate names generic. */ BundleSettings &BundleSettings::operator=(const BundleSettings &other) { if (&other != this) { @@ -158,15 +169,17 @@ namespace Isis { m_createInverseMatrix = other.m_createInverseMatrix; m_outlierRejection = other.m_outlierRejection; m_outlierRejectionMultiplier = other.m_outlierRejectionMultiplier; - m_globalLatitudeAprioriSigma = other.m_globalLatitudeAprioriSigma; - m_globalLongitudeAprioriSigma = other.m_globalLongitudeAprioriSigma; - m_globalRadiusAprioriSigma = other.m_globalRadiusAprioriSigma; + m_globalPointCoord1AprioriSigma = other.m_globalPointCoord1AprioriSigma; + m_globalPointCoord2AprioriSigma = other.m_globalPointCoord2AprioriSigma; + m_globalPointCoord3AprioriSigma = other.m_globalPointCoord3AprioriSigma; m_observationSolveSettings = other.m_observationSolveSettings; m_convergenceCriteria = other.m_convergenceCriteria; m_convergenceCriteriaThreshold = other.m_convergenceCriteriaThreshold; m_convergenceCriteriaMaximumIterations = other.m_convergenceCriteriaMaximumIterations; m_solveTargetBody = other.m_solveTargetBody; m_bundleTargetBody = other.m_bundleTargetBody; + m_cpCoordTypeReports = other.m_cpCoordTypeReports; + m_cpCoordTypeBundle = other.m_cpCoordTypeBundle; m_maximumLikelihood = other.m_maximumLikelihood; m_outputFilePrefix = other.m_outputFilePrefix; } @@ -219,41 +232,60 @@ namespace Isis { * @param errorPropagation A boolean value indicating whether to use the * cholmod library's error propagation. * @param solveRadius A boolean value indicating whether to solve for radius. - * @param globalLatitudeAprioriSigma The global a priori sigma for latitude. - * @param globalLongitudeAprioriSigma The global a priori sigma for longitude. - * @param globalRadiusAprioriSigma The global a priori sigma for radius. + * @param coordType The type of coordinates used for control points + * @param globalPointCoord1AprioriSigma The global a priori sigma for latitude. + * @param globalPointCoord2AprioriSigma The global a priori sigma for longitude. + * @param globalPointCoord3AprioriSigma The global a priori sigma for radius. */ void BundleSettings::setSolveOptions(bool solveObservationMode, bool updateCubeLabel, bool errorPropagation, bool solveRadius, - double globalLatitudeAprioriSigma, - double globalLongitudeAprioriSigma, - double globalRadiusAprioriSigma) { + SurfacePoint::CoordinateType coordTypeBundle, + SurfacePoint::CoordinateType coordTypeReports, + double globalPointCoord1AprioriSigma, + double globalPointCoord2AprioriSigma, + double globalPointCoord3AprioriSigma) { m_solveObservationMode = solveObservationMode; m_solveRadius = solveRadius; m_updateCubeLabel = updateCubeLabel; - m_errorPropagation = errorPropagation; + m_errorPropagation = errorPropagation; + m_cpCoordTypeReports = coordTypeReports; + m_cpCoordTypeBundle = coordTypeBundle; + // m_cpCoordTypeBundle = SurfacePoint::Latitudinal; - if (globalLatitudeAprioriSigma > 0.0) { // otherwise, we leave as default Isis::Null - m_globalLatitudeAprioriSigma = globalLatitudeAprioriSigma; + if (globalPointCoord1AprioriSigma > 0.0) { // otherwise, we leave as default Isis::Null + m_globalPointCoord1AprioriSigma = globalPointCoord1AprioriSigma; } else { - m_globalLatitudeAprioriSigma = Isis::Null; + m_globalPointCoord1AprioriSigma = Isis::Null; } - if (globalLongitudeAprioriSigma > 0.0) { - m_globalLongitudeAprioriSigma = globalLongitudeAprioriSigma; + if (globalPointCoord2AprioriSigma > 0.0) { + m_globalPointCoord2AprioriSigma = globalPointCoord2AprioriSigma; } else { - m_globalLongitudeAprioriSigma = Isis::Null; + m_globalPointCoord2AprioriSigma = Isis::Null; } - if (m_solveRadius && globalRadiusAprioriSigma > 0.0) { - m_globalRadiusAprioriSigma = globalRadiusAprioriSigma; + // This is ugly. *** TODO *** Revisit this section to try to find a cleaner solution. + // I think we will have to do similar checking other places. + // See pvlObject, save, (DAC 03-29-2017) + if (coordTypeBundle == SurfacePoint::Latitudinal) { + if (m_solveRadius && globalPointCoord3AprioriSigma > 0.0) { + m_globalPointCoord3AprioriSigma = globalPointCoord3AprioriSigma; + } + else { + m_globalPointCoord3AprioriSigma = Isis::Null; + } } - else { - m_globalRadiusAprioriSigma = Isis::Null; + else if (coordTypeBundle == SurfacePoint::Rectangular) { + if (globalPointCoord3AprioriSigma > 0.0) { + m_globalPointCoord3AprioriSigma = globalPointCoord3AprioriSigma; + } + else { + m_globalPointCoord3AprioriSigma = Isis::Null; + } } } @@ -289,6 +321,33 @@ namespace Isis { } + /** + * Indicates the control point coordinate type for reports. + * + * This method returns the control point coordinate setting for reporting control points. + * + * @return @b SurfacePoint::CoordinateType Returns the control point coordinate type setting + * + */ + SurfacePoint::CoordinateType BundleSettings::controlPointCoordTypeReports() const { + return (m_cpCoordTypeReports); + } + + + /** + * Indicates the control point coordinate type for the actual bundle adjust. + * + * This method returns the control point coordinate setting for performing the bundle adjust. + * + * @return @b SurfacePoint::CoordinateType Returns the control point coordinate type setting + * + * @see BundleAdjust::errorPropagation() + */ + SurfacePoint::CoordinateType BundleSettings::controlPointCoordTypeBundle() const { + return (m_cpCoordTypeBundle); + } + + /** * Indicates if the settings will allow the inverse correlation matrix to be created. * @@ -391,35 +450,32 @@ namespace Isis { /** - * Retrieves the global a priori sigma latitude value for this bundle - * adjustment. - * - * @return @b double The global a priori sigma for latitude. + * Retrieves global a priori sigma for 1st coordinate of points for this bundle + * + * @return @b double The global a priori sigma for point coordinate 1. */ - double BundleSettings::globalLatitudeAprioriSigma() const { - return m_globalLatitudeAprioriSigma; + double BundleSettings::globalPointCoord1AprioriSigma() const { + return m_globalPointCoord1AprioriSigma; } /** - * Retrieves the global a priori sigma longitude value for this bundle - * adjustment. - * - * @return @b double The global a priori sigma for longitude. + * Retrieves the global a priori sigma for 2nd coordinate of points for this bundle + * + * @return @b double The global a priori sigma for point coordinate 2. */ - double BundleSettings::globalLongitudeAprioriSigma() const { - return m_globalLongitudeAprioriSigma; + double BundleSettings::globalPointCoord2AprioriSigma() const { + return m_globalPointCoord2AprioriSigma; } /** - * Retrieves the global a priori sigma radius value for this bundle - * adjustment. - * - * @return @b double The global a priori sigma for radius. + * Retrieves the global a priori sigma 3rd coordinate of points for this bundle + * + * @return @b double The global a priori sigma for point coordinate 3. */ - double BundleSettings::globalRadiusAprioriSigma() const { - return m_globalRadiusAprioriSigma; + double BundleSettings::globalPointCoord3AprioriSigma() const { + return m_globalPointCoord3AprioriSigma; } @@ -961,6 +1017,9 @@ namespace Isis { * * @param stream The stream to write serialized XML output * @param project The project that contains the settings + * @internal + * @history 2017-05-30 Debbie A. Cook - Added controlPointCoordType to the xml stream + * and made global coordinate names generic. */ void BundleSettings::save(QXmlStreamWriter &stream, const Project *project) const { stream.writeStartElement("bundleSettings"); @@ -972,29 +1031,31 @@ namespace Isis { stream.writeStartElement("solveOptions"); stream.writeAttribute("solveObservationMode", toString(solveObservationMode())); stream.writeAttribute("solveRadius", toString(solveRadius())); + stream.writeAttribute("controlPointCoordTypeReports", toString(controlPointCoordTypeReports())); + stream.writeAttribute("controlPointCoordTypeBundle", toString(controlPointCoordTypeBundle())); stream.writeAttribute("updateCubeLabel", toString(updateCubeLabel())); stream.writeAttribute("errorPropagation", toString(errorPropagation())); stream.writeAttribute("createInverseMatrix", toString(createInverseMatrix())); stream.writeEndElement(); stream.writeStartElement("aprioriSigmas"); - if (IsSpecial(globalLatitudeAprioriSigma())) { - stream.writeAttribute("latitude", "N/A"); + if (IsSpecial(globalPointCoord1AprioriSigma())) { + stream.writeAttribute("pointCoord1", "N/A"); } else { - stream.writeAttribute("latitude", toString(globalLatitudeAprioriSigma())); + stream.writeAttribute("pointCoord1", toString(globalPointCoord1AprioriSigma())); } - if (IsSpecial(globalLongitudeAprioriSigma())) { - stream.writeAttribute("longitude", "N/A"); + if (IsSpecial(globalPointCoord2AprioriSigma())) { + stream.writeAttribute("pointCoord2", "N/A"); } else { - stream.writeAttribute("longitude", toString(globalLongitudeAprioriSigma())); + stream.writeAttribute("pointCoord2", toString(globalPointCoord2AprioriSigma())); } - if (IsSpecial(globalRadiusAprioriSigma())) { - stream.writeAttribute("radius", "N/A"); + if (IsSpecial(globalPointCoord3AprioriSigma())) { + stream.writeAttribute("pointCoord3", "N/A"); } else { - stream.writeAttribute("radius", toString(globalRadiusAprioriSigma())); + stream.writeAttribute("pointCoord3", toString(globalPointCoord3AprioriSigma())); } stream.writeEndElement(); @@ -1080,6 +1141,10 @@ namespace Isis { * @param attributes The list of attributes for the tag. * * @return @b bool Indicates whether to continue reading the XML (usually true). + * + * @internal + * @history 2017-05-30 Debbie A. Cook - Added controlPointCoordTypes to the pvl + * and made global coordinate names generic. */ bool BundleSettings::XmlHandler::startElement(const QString &namespaceURI, const QString &localName, @@ -1101,6 +1166,18 @@ namespace Isis { m_xmlHandlerBundleSettings->m_solveRadius = toBool(solveRadiusStr); } + QString coordTypeReportsStr = attributes.value("controlPointCoordinateTypeReports"); + if (!coordTypeReportsStr.isEmpty()) { + m_xmlHandlerBundleSettings->m_cpCoordTypeReports = + SurfacePoint::stringToCoordinateType(coordTypeReportsStr); + } + + QString coordTypeBundleStr = attributes.value("controlPointCoordinateTypeBundle"); + if (!coordTypeBundleStr.isEmpty()) { + m_xmlHandlerBundleSettings->m_cpCoordTypeBundle = + SurfacePoint::stringToCoordinateType(coordTypeBundleStr); + } + QString updateCubeLabelStr = attributes.value("updateCubeLabel"); if (!updateCubeLabelStr.isEmpty()) { m_xmlHandlerBundleSettings->m_updateCubeLabel = toBool(updateCubeLabelStr); @@ -1118,38 +1195,38 @@ namespace Isis { } else if (localName == "aprioriSigmas") { - QString globalLatitudeAprioriSigmaStr = attributes.value("latitude"); - m_xmlHandlerBundleSettings->m_globalLatitudeAprioriSigma = Isis::Null; + QString globalPointCoord1AprioriSigmaStr = attributes.value("pointCoord1"); + m_xmlHandlerBundleSettings->m_globalPointCoord1AprioriSigma = Isis::Null; // TODO: why do I need to init this one and not other sigmas??? - if (!globalLatitudeAprioriSigmaStr.isEmpty()) { - if (globalLatitudeAprioriSigmaStr == "N/A") { - m_xmlHandlerBundleSettings->m_globalLatitudeAprioriSigma = Isis::Null; + if (!globalPointCoord1AprioriSigmaStr.isEmpty()) { + if (globalPointCoord1AprioriSigmaStr == "N/A") { + m_xmlHandlerBundleSettings->m_globalPointCoord1AprioriSigma = Isis::Null; } else { - m_xmlHandlerBundleSettings->m_globalLatitudeAprioriSigma - = toDouble(globalLatitudeAprioriSigmaStr); + m_xmlHandlerBundleSettings->m_globalPointCoord1AprioriSigma + = toDouble(globalPointCoord1AprioriSigmaStr); } } - QString globalLongitudeAprioriSigmaStr = attributes.value("longitude"); - if (!globalLongitudeAprioriSigmaStr.isEmpty()) { - if (globalLongitudeAprioriSigmaStr == "N/A") { - m_xmlHandlerBundleSettings->m_globalLongitudeAprioriSigma = Isis::Null; + QString globalPointCoord2AprioriSigmaStr = attributes.value("pointCoord2"); + if (!globalPointCoord2AprioriSigmaStr.isEmpty()) { + if (globalPointCoord2AprioriSigmaStr == "N/A") { + m_xmlHandlerBundleSettings->m_globalPointCoord2AprioriSigma = Isis::Null; } else { - m_xmlHandlerBundleSettings->m_globalLongitudeAprioriSigma - = toDouble(globalLongitudeAprioriSigmaStr); + m_xmlHandlerBundleSettings->m_globalPointCoord2AprioriSigma + = toDouble(globalPointCoord2AprioriSigmaStr); } } - QString globalRadiusAprioriSigmaStr = attributes.value("radius"); - if (!globalRadiusAprioriSigmaStr.isEmpty()) { - if (globalRadiusAprioriSigmaStr == "N/A") { - m_xmlHandlerBundleSettings->m_globalRadiusAprioriSigma = Isis::Null; + QString globalPointCoord3AprioriSigmaStr = attributes.value("radius"); + if (!globalPointCoord3AprioriSigmaStr.isEmpty()) { + if (globalPointCoord3AprioriSigmaStr == "N/A") { + m_xmlHandlerBundleSettings->m_globalPointCoord3AprioriSigma = Isis::Null; } else { - m_xmlHandlerBundleSettings->m_globalRadiusAprioriSigma - = toDouble(globalRadiusAprioriSigmaStr); + m_xmlHandlerBundleSettings->m_globalPointCoord3AprioriSigma + = toDouble(globalPointCoord3AprioriSigmaStr); } } } diff --git a/isis/src/control/objs/BundleSettings/BundleSettings.h b/isis/src/control/objs/BundleSettings/BundleSettings.h index 323195bf76aa752b8aaa334d5d2fab6a4d87ec47..644ef62ba448fe41e5101ad383801222e362b221 100644 --- a/isis/src/control/objs/BundleSettings/BundleSettings.h +++ b/isis/src/control/objs/BundleSettings/BundleSettings.h @@ -35,6 +35,7 @@ #include "BundleObservationSolveSettings.h" #include "MaximumLikelihoodWFunctions.h" #include "SpecialPixel.h" +#include "SurfacePoint.h" #include "XmlStackedHandler.h" class QDataStream; @@ -109,6 +110,18 @@ namespace Isis { * @history 2018-06-28 Christopher Combs - Added observationSolveSettings() method to retrieve * m_observationSolveSettings. Fixes #497. * + * @history 2017-06-25 Debbie Cook - Added m_cpCoordTypeReports and m_cpCoordTypeBundle. + * The 2nd type determines how control point coordinates are entered + * into the the matrix and interpreted throughout the adjustment. The + * 1st type determines the coordinate type of control points in reports. + * Added the new coordinate type as an argument to SetSolveOptions. + * Changed GlobalAprioriSigmas names to more generic names: Latitude to + * PointCoord1, Longitude to PointCoord2, and Radius to PointCoord3 so + * they can be used for either lat/lon/radius or x/y/z. Also added + * accessor methods, CoordTypeReports() & CoordTypeBundle() + * for the new coordinate type members. + * References #4649 and #501. + * * @todo Determine which XmlStackedHandlerReader constructor is preferred * @todo Determine which XmlStackedHandler needs a Project pointer (see constructors) * @todo Determine whether QList m_observationSolveSettings @@ -154,15 +167,19 @@ namespace Isis { bool updateCubeLabel = false, bool errorPropagation = false, bool solveRadius = false, - double globalLatitudeAprioriSigma = Isis::Null, - double globalLongitudeAprioriSigma = Isis::Null, - double globalRadiusAprioriSigma = Isis::Null); - void setOutlierRejection(bool outlierRejection, + SurfacePoint::CoordinateType coordTypeBundle = SurfacePoint::Latitudinal, + SurfacePoint::CoordinateType coordTypeReports = SurfacePoint::Latitudinal, + double globalPointCoord1AprioriSigma = Isis::Null, + double globalPointCoord2AprioriSigma = Isis::Null, + double globalPointCoord3AprioriSigma = Isis::Null); + void setOutlierRejection(bool outlierRejection, double multiplier = 1.0); void setObservationSolveOptions(QList obsSolveSettingsList); void setCreateInverseMatrix(bool createMatrix); // accessors + SurfacePoint::CoordinateType controlPointCoordTypeReports() const; + SurfacePoint::CoordinateType controlPointCoordTypeBundle() const; bool createInverseMatrix() const; bool solveObservationMode() const; bool solveRadius() const; @@ -170,9 +187,10 @@ namespace Isis { bool errorPropagation() const; bool outlierRejection() const; double outlierRejectionMultiplier() const; - double globalLatitudeAprioriSigma() const; - double globalLongitudeAprioriSigma() const; - double globalRadiusAprioriSigma() const; +// These sigmas are either for planetocentric lat/lon/radius or body-fixed x/y/z + double globalPointCoord1AprioriSigma() const; + double globalPointCoord2AprioriSigma() const; + double globalPointCoord3AprioriSigma() const; int numberSolveSettings() const; BundleObservationSolveSettings observationSolveSettings(QString instrumentId) const; @@ -346,9 +364,9 @@ namespace Isis { Defaults to 1, so no change if rejection = false.*/ // Parameter Uncertainties (Weighting) - double m_globalLatitudeAprioriSigma; //!< The global a priori sigma for latitude. - double m_globalLongitudeAprioriSigma; //!< The global a priori sigma for longitude. - double m_globalRadiusAprioriSigma; //!< The global a priori sigma for radius. + double m_globalPointCoord1AprioriSigma; //!< The global a priori sigma for latitude or X. + double m_globalPointCoord2AprioriSigma; //!< The global a priori sigma for longitude or Y. + double m_globalPointCoord3AprioriSigma; //!< The global a priori sigma for radius or Z. // QList of observation solve settings QList m_observationSolveSettings; //!< @@ -379,7 +397,11 @@ namespace Isis { bool m_solveTargetBody; //!< Indicates whether to solve for target body. BundleTargetBodyQsp m_bundleTargetBody; /**< A pointer to the target body settings and information.*/ - + // Control Points + SurfacePoint::CoordinateType m_cpCoordTypeReports; /**< Indicates the coordinate type for + outputting control points in reports. */ + SurfacePoint::CoordinateType m_cpCoordTypeBundle; /**< Indicates the coordinate type used + for control points in the bundle adjustment */ // Output Options QString m_outputFilePrefix; /**< The prefix for all output files. If the user does not want output files to be written to the current directory, the diff --git a/isis/src/control/objs/BundleSettings/BundleSettings.truth b/isis/src/control/objs/BundleSettings/BundleSettings.truth index 1426a8bf77628a193162c58703ec50e93564ee2e..687aba81b7c8a774f3b89779d348b76238740e1c 100644 --- a/isis/src/control/objs/BundleSettings/BundleSettings.truth +++ b/isis/src/control/objs/BundleSettings/BundleSettings.truth @@ -4,8 +4,8 @@ Printing PVL group with settings from the default constructor... Yes - - + + @@ -33,8 +33,8 @@ Testing copy constructor... Yes - - + + @@ -62,8 +62,8 @@ Testing assignment operator to set this equal to itself... Yes - - + + @@ -91,8 +91,8 @@ Testing assignment operator to create a new settings object... Yes - - + + @@ -120,8 +120,8 @@ Testing mutator methods... Yes - - + + @@ -170,8 +170,8 @@ Testing mutator methods... Yes - - + + @@ -198,8 +198,8 @@ Testing mutator methods... Yes - - + + @@ -275,8 +275,8 @@ Serializing test XML object to file: Yes - - + + @@ -304,8 +304,8 @@ Testing XML: Object deserialized as (should match object above): Yes - - + + @@ -334,8 +334,8 @@ Serializing test XML object to file: Yes - - + + @@ -385,8 +385,8 @@ Testing XML: Object deserialized as (should match object above): Yes - - + + diff --git a/isis/src/control/objs/BundleSettings/unitTest.cpp b/isis/src/control/objs/BundleSettings/unitTest.cpp index 54d3e40663e41d5d657980454c2bd5c0243682c4..a3b7ea89c0b743c18aa1135b87863bc8ba733e0b 100755 --- a/isis/src/control/objs/BundleSettings/unitTest.cpp +++ b/isis/src/control/objs/BundleSettings/unitTest.cpp @@ -49,6 +49,9 @@ void printXml(const T &); * Fixes #4797. * @history 2018-05-24 Ken Edmundson - Updated truth data to indicate default value for * m_createInverseMatrix was changed from true to false. + * @history 2018-06-04 Debbie A. Cook - (added to BundleXYZ branch on 2017-06-25) Updated to + * reflect added argument for control pointcoordinate type. References + * #4649 and #501. * * @todo Truth updated so that the name of the BundleObservationSolveSettings object is Null, * this should be fixed as part of #4292. @@ -168,8 +171,10 @@ int main(int argc, char *argv[]) { // reset all... // validate the network copySettings.setValidateNetwork(true); + // Assume for now the user interface will prevent any invalid coordinate types in the // set the solve options - copySettings.setSolveOptions(true, true, true, true, 1000.0, 2000.0, 3000.0); + copySettings.setSolveOptions(true, true, true, true, SurfacePoint::Rectangular, + SurfacePoint::Rectangular, 1000.0, 2000.0, 3000.0); // set outlier rejection copySettings.setOutlierRejection(true, 4.0); // create and fill the list of observation solve settings... then set @@ -205,7 +210,7 @@ int main(int argc, char *argv[]) { // now for test coverage, call some more resets // SolveObservationMode = UpdateCubeLabel = ErrorPropagation = true and // SolveRadius = OutlierRejection = false - settings.setSolveOptions(true, true, true, false); + settings.setSolveOptions(true, true, true, false, SurfacePoint::Latitudinal); settings.setOutlierRejection(false); settings.setOutputFilePrefix("TestFilePrefix"); printXml(settings); diff --git a/isis/src/control/objs/BundleSolutionInfo/BundleSolutionInfo.cpp b/isis/src/control/objs/BundleSolutionInfo/BundleSolutionInfo.cpp index d9c53bd6cb466e3acea682128ccb73ccd22f7535..779d82b5b16d6521fc21e75bd8917b70f52ad0e4 100755 --- a/isis/src/control/objs/BundleSolutionInfo/BundleSolutionInfo.cpp +++ b/isis/src/control/objs/BundleSolutionInfo/BundleSolutionInfo.cpp @@ -588,6 +588,16 @@ namespace Isis { sprintf(buf, "\n ERROR PROPAGATION: OFF"); fpOut << buf; + (m_settings->controlPointCoordTypeReports() == SurfacePoint::Latitudinal) ? + sprintf(buf, "\n CONTROL POINT COORDINATE TYPE FOR REPORTS: LATITUDINAL"): + sprintf(buf, "\n CONTROL POINT COORDINATE TYPE FOR REPORTS: RECTANGULAR"); + fpOut << buf; + + (m_settings->controlPointCoordTypeBundle() == SurfacePoint::Latitudinal) ? + sprintf(buf, "\n CONTROL POINT COORDINATE TYPE FOR BUNDLE: LATITUDINAL"): + sprintf(buf, "\n CONTROL POINT COORDINATE TYPE FOR BUNDLE: RECTANGULAR"); + fpOut << buf; + if (m_settings->outlierRejection()) { sprintf(buf, "\n OUTLIER REJECTION: ON"); fpOut << buf; @@ -603,6 +613,14 @@ namespace Isis { fpOut << buf; } + // Added April 5, 2017 + sprintf(buf, "\n CONTROL POINT COORDINATE TYPE FOR REPORTS: %s", + SurfacePoint::coordinateTypeToString(m_settings->controlPointCoordTypeReports()).toLatin1().data()); + + // Added July 4, 2017 + sprintf(buf, "\n CONTROL POINT COORDINATE TYPE FOR BUNDLE: %s", + SurfacePoint::coordinateTypeToString(m_settings->controlPointCoordTypeBundle()).toLatin1().data()); + sprintf(buf, "\n\nMAXIMUM LIKELIHOOD ESTIMATION\n============================\n"); fpOut << buf; @@ -718,21 +736,45 @@ namespace Isis { fpOut << buf; sprintf(buf, "\n\nINPUT: GLOBAL IMAGE PARAMETER UNCERTAINTIES\n===========================================\n"); + QString coord1Str; + QString coord2Str; + QString coord3Str; + switch (m_settings->controlPointCoordTypeReports()) { + case SurfacePoint::Latitudinal: + coord1Str = "LATITUDE"; + coord2Str = "LONGITUDE"; + coord3Str = "RADIUS"; + break; + case SurfacePoint::Rectangular: + coord1Str = " X"; + coord2Str = " Y"; + coord3Str = " Z"; + break; + default: + IString msg ="Unknown surface point coordinate type enum [" + + toString(m_settings->controlPointCoordTypeReports()) + "]." ; + throw IException(IException::Programmer, msg, _FILEINFO_); + break; + } + + // Coordinate 1 (latitude or point X) fpOut << buf; - (m_settings->globalLatitudeAprioriSigma() == Isis::Null) ? - sprintf(buf,"\n POINT LATITUDE SIGMA: N/A"): - sprintf(buf,"\n POINT LATITUDE SIGMA: %lf (meters)", - m_settings->globalLatitudeAprioriSigma()); + (m_settings->globalPointCoord1AprioriSigma() == Isis::Null) ? + sprintf(buf,"\n POINT %s SIGMA: N/A", coord1Str.toLatin1().data()): + sprintf(buf,"\n POINT %s SIGMA: %lf (meters)", coord1Str.toLatin1().data(), + m_settings->globalPointCoord1AprioriSigma()); + // Coordinate 2 (longitude or point Y) fpOut << buf; - (m_settings->globalLongitudeAprioriSigma() == Isis::Null) ? - sprintf(buf,"\n POINT LONGITUDE SIGMA: N/A"): - sprintf(buf,"\n POINT LONGITUDE SIGMA: %lf (meters)", - m_settings->globalLongitudeAprioriSigma()); + (m_settings->globalPointCoord2AprioriSigma() == Isis::Null) ? + sprintf(buf,"\n POINT %s SIGMA: N/A", coord2Str.toLatin1().data()): + sprintf(buf,"\n POINT %s SIGMA: %lf (meters)", coord2Str.toLatin1().data(), + m_settings->globalPointCoord2AprioriSigma()); + // Coordinate 3 (radius or point Z) fpOut << buf; - (m_settings->globalRadiusAprioriSigma() == Isis::Null) ? - sprintf(buf,"\n POINT RADIUS SIGMA: N/A"): - sprintf(buf,"\n POINT RADIUS SIGMA: %lf (meters)", - m_settings->globalRadiusAprioriSigma()); + (m_settings->globalPointCoord3AprioriSigma() == Isis::Null) ? + sprintf(buf,"\n POINT %s SIGMA: N/A", coord3Str.toLatin1().data()): + sprintf(buf,"\n POINT %s SIGMA: %lf (meters)", coord3Str.toLatin1().data(), + m_settings->globalPointCoord3AprioriSigma()); fpOut << buf; (positionSolveDegree < 1 || positionSigmas[0] == Isis::Null) ? sprintf(buf,"\n SPACECRAFT POSITION SIGMA: N/A"): @@ -1205,39 +1247,52 @@ namespace Isis { if (berrorProp) { sprintf(buf, "\n\n\nPOINTS UNCERTAINTY SUMMARY\n==========================\n\n"); fpOut << buf; - sprintf(buf, " RMS Sigma Latitude(m)%20.8lf\n", - m_statisticsResults->sigmaLatitudeStatisticsRms()); + + // Coordinate 1 (latitude or point x) summary + QString + coordName = surfacePointCoordName(m_settings->controlPointCoordTypeReports(), + SurfacePoint::One); + sprintf(buf, "RMS Sigma %s(m)%20.8lf\n", coordName.toLatin1().data(), + m_statisticsResults->sigmaCoord1StatisticsRms()); fpOut << buf; - sprintf(buf, " MIN Sigma Latitude(m)%20.8lf at %s\n", - m_statisticsResults->minSigmaLatitudeDistance().meters(), - m_statisticsResults->minSigmaLatitudePointId().toLatin1().data()); + sprintf(buf, "MIN Sigma %s(m)%20.8lf at %s\n", coordName.toLatin1().data(), + m_statisticsResults->minSigmaCoord1Distance().meters(), + m_statisticsResults->minSigmaCoord1PointId().toLatin1().data()); fpOut << buf; - sprintf(buf, " MAX Sigma Latitude(m)%20.8lf at %s\n\n", - m_statisticsResults->maxSigmaLatitudeDistance().meters(), - m_statisticsResults->maxSigmaLatitudePointId().toLatin1().data()); + sprintf(buf, "MAX Sigma %s(m)%20.8lf at %s\n\n", coordName.toLatin1().data(), + m_statisticsResults->maxSigmaCoord1Distance().meters(), + m_statisticsResults->maxSigmaCoord1PointId().toLatin1().data()); fpOut << buf; - sprintf(buf, "RMS Sigma Longitude(m)%20.8lf\n", - m_statisticsResults->sigmaLongitudeStatisticsRms()); + + // Coordinate 2 (longitude or point y) summary + coordName = surfacePointCoordName(m_settings->controlPointCoordTypeReports(), + SurfacePoint::Two); + sprintf(buf, "RMS Sigma %s(m)%20.8lf\n", coordName.toLatin1().data(), + m_statisticsResults->sigmaCoord2StatisticsRms()); fpOut << buf; - sprintf(buf, "MIN Sigma Longitude(m)%20.8lf at %s\n", - m_statisticsResults->minSigmaLongitudeDistance().meters(), - m_statisticsResults->minSigmaLongitudePointId().toLatin1().data()); + sprintf(buf, "MIN Sigma %s(m)%20.8lf at %s\n", coordName.toLatin1().data(), + m_statisticsResults->minSigmaCoord2Distance().meters(), + m_statisticsResults->minSigmaCoord2PointId().toLatin1().data()); fpOut << buf; - sprintf(buf, "MAX Sigma Longitude(m)%20.8lf at %s\n\n", - m_statisticsResults->maxSigmaLongitudeDistance().meters(), - m_statisticsResults->maxSigmaLongitudePointId().toLatin1().data()); + sprintf(buf, "MAX Sigma %s(m)%20.8lf at %s\n\n", coordName.toLatin1().data(), + m_statisticsResults->maxSigmaCoord2Distance().meters(), + m_statisticsResults->maxSigmaCoord2PointId().toLatin1().data()); fpOut << buf; + + // Coordinate 3 (radius or point z) summary + coordName = surfacePointCoordName(m_settings->controlPointCoordTypeReports(), + SurfacePoint::Three); if ( m_settings->solveRadius() ) { - sprintf(buf, " RMS Sigma Radius(m)%20.8lf\n", - m_statisticsResults->sigmaRadiusStatisticsRms()); + sprintf(buf, "RMS Sigma %s(m)%20.8lf\n", coordName.toLatin1().data(), + m_statisticsResults->sigmaCoord3StatisticsRms()); fpOut << buf; - sprintf(buf, " MIN Sigma Radius(m)%20.8lf at %s\n", - m_statisticsResults->minSigmaRadiusDistance().meters(), - m_statisticsResults->minSigmaRadiusPointId().toLatin1().data()); + sprintf(buf, "MIN Sigma %s(m)%20.8lf at %s\n", coordName.toLatin1().data(), + m_statisticsResults->minSigmaCoord3Distance().meters(), + m_statisticsResults->minSigmaCoord3PointId().toLatin1().data()); fpOut << buf; - sprintf(buf, " MAX Sigma Radius(m)%20.8lf at %s\n", - m_statisticsResults->maxSigmaRadiusDistance().meters(), - m_statisticsResults->maxSigmaRadiusPointId().toLatin1().data()); + sprintf(buf, "MAX Sigma %s(m)%20.8lf at %s\n", coordName.toLatin1().data(), + m_statisticsResults->maxSigmaCoord3Distance().meters(), + m_statisticsResults->maxSigmaCoord3PointId().toLatin1().data()); fpOut << buf; } else { @@ -1251,11 +1306,20 @@ namespace Isis { } // output point summary data header - sprintf(buf, "\n\nPOINTS SUMMARY\n==============\n%103s" + if (m_settings->controlPointCoordTypeReports() == SurfacePoint::Latitudinal) { + sprintf(buf, "\n\nPOINTS SUMMARY\n==============\n%103s" "Sigma Sigma Sigma\n" " Label Status Rays RMS" " Latitude Longitude Radius" " Latitude Longitude Radius\n", ""); + } + else { // Must be Rectangular + sprintf(buf, "\n\nPOINTS SUMMARY\n==============\n%103s" + "Sigma Sigma Sigma\n" + " Label Status Rays RMS" + " Point X Point Y Point Z" + " Point X Point Y Point Z\n", ""); + } fpOut << buf; int nPoints = m_statisticsResults->bundleControlPoints().size(); @@ -1276,9 +1340,9 @@ namespace Isis { for (int i = 0; i < nPoints; i++) { BundleControlPointQsp bundleControlPoint = m_statisticsResults->bundleControlPoints().at(i); + // Removed radiansToMeters argument 9/18/2018 DAC QString pointDetailString = bundleControlPoint->formatBundleOutputDetailString(berrorProp, - m_statisticsResults->radiansToMeters(), solveRadius); fpOut << (const char*)pointDetailString.toLatin1().data(); } @@ -1357,8 +1421,9 @@ namespace Isis { // point corrections and initial sigmas boost::numeric::ublas::bounded_vector< double, 3 > corrections = bundlecontrolpoint-> corrections(); - cor_lat_m = corrections[0]*m_statisticsResults->radiansToMeters(); - cor_lon_m = corrections[1]*m_statisticsResults->radiansToMeters()*cos(dLat*Isis::DEG2RAD); + // Now use the local radius to convert radians to meters instead of the target body equatorial radius + cor_lat_m = bundlecontrolpoint->adjustedSurfacePoint().LatitudeToMeters(corrections[0]); + cor_lon_m = bundlecontrolpoint->adjustedSurfacePoint().LongitudeToMeters(corrections[1]); cor_rad_m = corrections[2]*1000.0; if (bundlecontrolpoint->type() == ControlPoint::Fixed) { @@ -1385,7 +1450,7 @@ namespace Isis { numMeasures, numRejectedMeasures, dResidualRms, dLat, dLon, dRadius, dSigmaLat, dSigmaLong, dSigmaRadius, cor_lat_m, cor_lon_m, cor_rad_m, dX, dY, dZ); } - else + else sprintf(buf, "%s,%s,%d,%d,%6.2lf,%16.8lf,%16.8lf,%16.8lf,%16.8lf,%16.8lf,%16.8lf,%16.8lf," "%16.8lf,%16.8lf\n", bundlecontrolpoint->id().toLatin1().data(), strStatus.toLatin1().data(), @@ -1762,4 +1827,62 @@ namespace Isis { m_xmlHandlerCharacters = ""; return XmlStackedHandler::endElement(namespaceURI, localName, qName); } + + + /** + * Determine the control point coordinate name. + * + * @param type The control point coordinate type (see SurfacePoint.h) + * @param coordIdx The coordinate index (see SurfacePoint.h) + * + * @return @b QString Coordinate name + */ + QString BundleSolutionInfo::surfacePointCoordName(SurfacePoint::CoordinateType type, + SurfacePoint::CoordIndex coordIdx) const { + QString coordName; + switch (m_settings->controlPointCoordTypeReports()) { + case SurfacePoint::Latitudinal: + switch (coordIdx) { + case SurfacePoint::One: + coordName = " Latitude"; + break; + case SurfacePoint::Two: + coordName = "Longitude"; + break; + case SurfacePoint::Three: + coordName = " Radius"; + break; + default: + IString msg = "Unknown surface point index enum [" + + toString(coordIdx) + "]."; + throw IException(IException::Programmer, msg, _FILEINFO_); + break; + } + break; + case SurfacePoint::Rectangular: + switch (coordIdx) { + case SurfacePoint::One: + coordName = "POINT X"; + break; + case SurfacePoint::Two: + coordName = "POINT Y"; + break; + case SurfacePoint::Three: + coordName = "POINT Z"; + break; + default: + IString msg = "Unknown surface point index enum [" + + toString(coordIdx) + "]."; + throw IException(IException::Programmer, msg, _FILEINFO_); + break; + } + break; + default: + IString msg = "Unknown surface point coordinate type enum [" + + toString(m_settings->controlPointCoordTypeReports()) + "]."; + throw IException(IException::Programmer, msg, _FILEINFO_); + break; + } + return coordName; + } } diff --git a/isis/src/control/objs/BundleSolutionInfo/BundleSolutionInfo.h b/isis/src/control/objs/BundleSolutionInfo/BundleSolutionInfo.h index 52a90cb1e4c2fe003a1d0f231752c0182979bf7e..00303a8178c1997c19bfb616782309b02af0400a 100755 --- a/isis/src/control/objs/BundleSolutionInfo/BundleSolutionInfo.h +++ b/isis/src/control/objs/BundleSolutionInfo/BundleSolutionInfo.h @@ -27,6 +27,7 @@ #include #include "BundleSettings.h" +#include "SurfacePoint.h" #include "XmlStackedHandler.h" @@ -147,6 +148,13 @@ namespace Isis { * because BundleSolutionInfo is derived from QObject (see comment * below). Removed copy constructor and assignment operator from cpp * file. + * @history 2018-06-01 Debbie A. Cook - ( Added 2018-02-21 to BundleXYZ branch) Added + * coordinate types to report and appropriate headings for columns based + * on the coordinate type. Also added a utility method to return the + * coordinate name based on coordinate type and coordinate index. + * References #4649 and #501. + * @history 2018-09-18 Debbie A. Cook - Removed radiansToMeters argument. References + * #4649 and #501 */ class BundleSolutionInfo : public QObject { Q_OBJECT @@ -195,6 +203,9 @@ namespace Isis { void save(QXmlStreamWriter &stream, const Project *project, FileName newProjectRoot) const; + QString surfacePointCoordName(SurfacePoint::CoordinateType type, + SurfacePoint::CoordIndex coordInx) const; + public slots: void updateFileName(Project *); @@ -220,6 +231,8 @@ namespace Isis { virtual bool characters(const QString &ch); virtual bool endElement(const QString &namespaceURI, const QString &localName, const QString &qName); + QString surfacePointCoordName(SurfacePoint::CoordinateType type, + SurfacePoint::CoordIndex coordIdx) const; private: Q_DISABLE_COPY(XmlHandler); diff --git a/isis/src/control/objs/BundleSolutionInfo/BundleSolutionInfo.truth b/isis/src/control/objs/BundleSolutionInfo/BundleSolutionInfo.truth index d94fd75d91e90fb84e38433e3c1fdf0be65bbebf..e41ca66ecc109f930d77aa3aa854033fc7341d64 100644 --- a/isis/src/control/objs/BundleSolutionInfo/BundleSolutionInfo.truth +++ b/isis/src/control/objs/BundleSolutionInfo/BundleSolutionInfo.truth @@ -16,8 +16,8 @@ Created new BundleSettings... Yes - - + + @@ -110,8 +110,8 @@ Serializing test XML object to file... Yes - - + + @@ -203,8 +203,8 @@ Testing XML: Object deserialized as (should match object above): Yes - - + + @@ -295,8 +295,8 @@ Testing mutator methods... Yes - - + + @@ -398,8 +398,8 @@ Serializing test XML object to file... Yes - - + + @@ -502,8 +502,8 @@ Testing XML: Object deserialized as (should match object above): Yes - - + + diff --git a/isis/src/control/objs/BundleSolutionInfo/unitTest.cpp b/isis/src/control/objs/BundleSolutionInfo/unitTest.cpp index 547fa6b5b95e5cbc8c83c998851a6ddea1c3df80..2751b0a09081f88a1c8b260dd931fb16e4fef201 100755 --- a/isis/src/control/objs/BundleSolutionInfo/unitTest.cpp +++ b/isis/src/control/objs/BundleSolutionInfo/unitTest.cpp @@ -122,8 +122,12 @@ int main(int argc, char *argv[]) { ControlNet outNet; outNet.AddPoint(freePoint); outNet.AddPoint(fixedPoint); - BundleControlPointQsp freeBundleControlPoint(new BundleControlPoint(freePoint)); - BundleControlPointQsp fixedBundleControlPoint(new BundleControlPoint(fixedPoint)); + // Obsolete argument - now using local radius. + // double metersToRadians = 1./23.68; // Use what BundleResults used + BundleControlPointQsp freeBundleControlPoint( + new BundleControlPoint(settings, freePoint)); + BundleControlPointQsp fixedBundleControlPoint( + new BundleControlPoint(settings, fixedPoint)); QVector bundleControlPointVector; bundleControlPointVector.append(freeBundleControlPoint); bundleControlPointVector.append(fixedBundleControlPoint); @@ -167,6 +171,9 @@ int main(int argc, char *argv[]) { qDebug() << "Testing XML: reading serialized BundleResults back in..."; XmlStackedHandlerReader reader1; BundleSolutionInfoXmlHandlerTester bsFromXml1(project, &reader1, xmlFile1); + // Now manually set the control net in BundleSolutionInfo's BundleResults to + // complete its initialization. This seems awkward. + bsFromXml1.bundleResults().setOutputControlNet(ControlNetQsp(new ControlNet(outNet))); qDebug() << "Testing XML: Object deserialized as (should match object above):"; printXml(bsFromXml1); // Save comparison output to log file diff --git a/isis/src/control/objs/BundleUtilities/BundleControlPoint.cpp b/isis/src/control/objs/BundleUtilities/BundleControlPoint.cpp index d437cf2a6d085015941d4446e92fd53ce872ba3a..01ebc9a490f5c8a19e95ca4af38058067feb1912 100644 --- a/isis/src/control/objs/BundleUtilities/BundleControlPoint.cpp +++ b/isis/src/control/objs/BundleUtilities/BundleControlPoint.cpp @@ -2,9 +2,15 @@ #include +// boost lib +#include + +// Isis lib #include "ControlMeasure.h" #include "Latitude.h" +#include "LinearAlgebra.h" #include "Longitude.h" +#include "SparseBlockMatrix.h" #include "SpecialPixel.h" namespace Isis { @@ -13,11 +19,11 @@ namespace Isis { /** * Constructs a BundleControlPoint object from a ControlPoint. Only the * non-ignored measures are added to the BundleControlPoint. - * * @param controlPoint Pointer to a ControlPoint that will be used to * construct this BundleControlPoint. */ - BundleControlPoint::BundleControlPoint(ControlPoint *controlPoint) { + BundleControlPoint::BundleControlPoint(const BundleSettingsQsp bundleSettings, + ControlPoint *controlPoint) { m_controlPoint = controlPoint; // setup vector of BundleMeasures for this control point @@ -45,6 +51,12 @@ namespace Isis { m_adjustedSigmas[0] = Isis::Null; m_adjustedSigmas[1] = Isis::Null; m_adjustedSigmas[2] = Isis::Null; + + // initialize coordinate type from settings + // m_coordType = SurfacePoint::Latitudinal; + m_coordTypeReports = bundleSettings->controlPointCoordTypeReports(); + m_coordTypeBundle = bundleSettings->controlPointCoordTypeBundle(); + setWeights(bundleSettings); } @@ -75,7 +87,7 @@ namespace Isis { // sanity check clear(); - + m_controlPoint = src.m_controlPoint; int numMeasures = src.size(); @@ -88,6 +100,9 @@ namespace Isis { m_adjustedSigmas = src.m_adjustedSigmas; m_weights = src.m_weights; m_nicVector = src.m_nicVector; + m_coordTypeReports = src.m_coordTypeReports; + m_coordTypeBundle = src.m_coordTypeBundle; + // *** TODO *** Why is the cholmodQMatrix not copied? Ask Ken } @@ -160,13 +175,11 @@ namespace Isis { * @param settings A QSharedPointer to BundleSettings object. * @param metersToRadians A double precision conversion factor. */ - void BundleControlPoint::setWeights(const BundleSettingsQsp settings, double metersToRadians) { - - double d; + void BundleControlPoint::setWeights(const BundleSettingsQsp settings) { - double globalLatitudeAprioriSigma = settings->globalLatitudeAprioriSigma(); - double globalLongitudeAprioriSigma = settings->globalLongitudeAprioriSigma(); - double globalRadiusAprioriSigma = settings->globalRadiusAprioriSigma(); + double globalPointCoord1AprioriSigma = settings->globalPointCoord1AprioriSigma(); + double globalPointCoord2AprioriSigma = settings->globalPointCoord2AprioriSigma(); + double globalPointCoord3AprioriSigma = settings->globalPointCoord3AprioriSigma(); if (m_controlPoint->GetType() == ControlPoint::Fixed) { m_weights[0] = 1.0e+50; @@ -174,65 +187,74 @@ namespace Isis { m_weights[2] = 1.0e+50; // m_aprioriSigmas = Isis::Null by default } + if (m_controlPoint->GetType() == ControlPoint::Free) { - if (!IsSpecial(globalLatitudeAprioriSigma)) { - m_aprioriSigmas[0] = globalLatitudeAprioriSigma; - d = globalLatitudeAprioriSigma*metersToRadians; - m_weights[0] = 1.0/(d*d); - } // else m_aprioriSigma = Isis::Null - // m_weights = 0.0 - if (!IsSpecial(globalLongitudeAprioriSigma)) { - m_aprioriSigmas[1] = globalLongitudeAprioriSigma; - d = globalLongitudeAprioriSigma*metersToRadians; - m_weights[1] = 1.0/(d*d); + // Global sigmas are temporary and should not be stored in the control net. Currently + // global sigmas are always in meters. Make sure unit of weights is 1/(var unit squared), + // where var is a value being solved for in the adjustment. Latitude and longitude are in + // radians and everything else is in km. + if (!IsSpecial(globalPointCoord1AprioriSigma)) { + setSigmaWeightFromGlobals(globalPointCoord1AprioriSigma, 0); } // else m_aprioriSigma = Isis::Null // m_weights = 0.0 - if (!settings->solveRadius()) { + if (!IsSpecial(globalPointCoord2AprioriSigma)) { + m_aprioriSigmas[1] = globalPointCoord2AprioriSigma; + setSigmaWeightFromGlobals(globalPointCoord2AprioriSigma, 1); + }// else m_aprioriSigma = Isis::Null + // m_weights = 0.0 + if (m_coordTypeBundle == SurfacePoint::Latitudinal && !settings->solveRadius()) { m_weights[2] = 1.0e+50; } else { - if (!IsSpecial(globalRadiusAprioriSigma)) { - m_aprioriSigmas[2] = globalRadiusAprioriSigma; - d = globalRadiusAprioriSigma*0.001; - m_weights[2] = 1.0/(d*d); + if (!IsSpecial(globalPointCoord3AprioriSigma)) { + setSigmaWeightFromGlobals(globalPointCoord3AprioriSigma, 2); } } } if (m_controlPoint->GetType() == ControlPoint::Constrained) { - if ( m_controlPoint->IsLatitudeConstrained() ) { - m_aprioriSigmas[0] = m_controlPoint->GetAprioriSurfacePoint().GetLatSigmaDistance().meters(); - m_weights[0] = m_controlPoint->GetAprioriSurfacePoint().GetLatWeight(); + // *** Be careful...Is m_aprioriSigmas an output (for reports) or bundle variable? *** + + // Assuming the member variable sigmas are for output reports (internal use only) so use + // the report coordinate type to calculate. All point sigmas are in meters. Radius weights + // are in 1/km^2. Make x/y/z weights the same because BundleAdjust works in km. + // Weights and corrections go into the bundle so use bundle coordinate type. + if ( m_controlPoint->IsCoord1Constrained() ) { + m_aprioriSigmas[0] = + m_controlPoint->GetAprioriSurfacePoint().GetSigmaDistance + (m_coordTypeReports, SurfacePoint::One).meters(); + m_weights[0] = + m_controlPoint->GetAprioriSurfacePoint().GetWeight(m_coordTypeBundle, SurfacePoint::One); } - else if (!IsSpecial(globalLatitudeAprioriSigma)) { - m_aprioriSigmas[0] = globalLatitudeAprioriSigma; - d = globalLatitudeAprioriSigma*metersToRadians; - m_weights[0] = 1.0/(d*d); + else if (!IsSpecial(globalPointCoord1AprioriSigma)) { + setSigmaWeightFromGlobals(globalPointCoord1AprioriSigma, 0); } // else not constrained and global sigma is Null, then m_aprioriSigmas = Isis::Null // m_weights = 0.0 - if ( m_controlPoint->IsLongitudeConstrained() ) { - m_aprioriSigmas[1] = m_controlPoint->GetAprioriSurfacePoint().GetLonSigmaDistance().meters(); - m_weights[1] = m_controlPoint->GetAprioriSurfacePoint().GetLonWeight(); + if ( m_controlPoint->IsCoord2Constrained() ) { + m_aprioriSigmas[1] = + m_controlPoint->GetAprioriSurfacePoint().GetSigmaDistance + (m_coordTypeReports, SurfacePoint::Two).meters(); + m_weights[1] = + m_controlPoint->GetAprioriSurfacePoint().GetWeight(m_coordTypeBundle, SurfacePoint::Two); } - else if (!IsSpecial(globalLongitudeAprioriSigma)) { - m_aprioriSigmas[1] = globalLongitudeAprioriSigma; - d = globalLongitudeAprioriSigma*metersToRadians; - m_weights[1] = 1.0/(d*d); + else if (!IsSpecial(globalPointCoord2AprioriSigma)) { + setSigmaWeightFromGlobals(globalPointCoord2AprioriSigma, 1); } // else not constrained and global sigma is Null, then m_aprioriSigmas = Isis::Null // m_weights = 0.0 - if (!settings->solveRadius()) { + if (m_coordTypeBundle == SurfacePoint::Latitudinal && !settings->solveRadius()) { m_weights[2] = 1.0e+50; } else { - if ( m_controlPoint->IsRadiusConstrained() ) { - m_aprioriSigmas[2] = m_controlPoint->GetAprioriSurfacePoint().GetLocalRadiusSigma().meters(); - m_weights[2] = m_controlPoint->GetAprioriSurfacePoint().GetLocalRadiusWeight(); + if ( m_controlPoint->IsCoord3Constrained() ) { + m_aprioriSigmas[2] = + m_controlPoint->GetAprioriSurfacePoint().GetSigmaDistance + (m_coordTypeReports, SurfacePoint::Three).meters(); + m_weights[2] = m_controlPoint->GetAprioriSurfacePoint().GetWeight + (m_coordTypeBundle, SurfacePoint::Three); } - else if (!IsSpecial(globalRadiusAprioriSigma)) { - m_aprioriSigmas[2] = globalRadiusAprioriSigma; - d = globalRadiusAprioriSigma*0.001; - m_weights[2] = 1.0/(d*d); + else if (!IsSpecial(globalPointCoord3AprioriSigma)) { + setSigmaWeightFromGlobals(globalPointCoord3AprioriSigma, 2); } // else not constrained and global sigma is Null, then m_aprioriSigmas = Isis::Null // m_weights = 0.0 } @@ -240,6 +262,76 @@ namespace Isis { } + /** + * Sets the member sigmas and weights from a global sigma.. + * +// *** TODO *** Should index be SurfacePoint::CoordIndex? + * @param gSigma The global sigma to assign. + * @param index The index of the point coordinate being set (0, 1, or 2). + * @param cFactor The conversion factor applied to gSigma to match bundle variable units. + * + * @see formatAprioriSigmaString() + */ + void BundleControlPoint::setSigmaWeightFromGlobals(double gSigma, int index) { + m_aprioriSigmas[index] = gSigma; + + switch (index) { + case 0: + if (m_coordTypeBundle == SurfacePoint::Latitudinal) { + m_aprioriSigmas[index] = gSigma; + double sigmaRadians = + m_controlPoint->GetAprioriSurfacePoint().MetersToLatitude(gSigma); // m to radians + if (sigmaRadians > DBL_EPSILON) { + m_weights[index] = 1. / (sigmaRadians*sigmaRadians); // 1/radians^2 + } + } + else if (m_coordTypeBundle == SurfacePoint::Rectangular) { + double sigmakm = gSigma * .001; // km + if (sigmakm > DBL_EPSILON) { + m_weights[0] = 1./ (sigmakm*sigmakm); // 1/km^2 + } + } + else { + IString msg ="Unknown surface point coordinate type enum [" + + toString(m_coordTypeBundle) + "]." ; + throw IException(IException::Programmer, msg, _FILEINFO_); + } + break; + case 1: + // if (!IsSpecial(globalPointCoord2AprioriSigma)) { + if (m_coordTypeBundle == SurfacePoint::Latitudinal) { + double sigmaRadians = + m_controlPoint->GetAprioriSurfacePoint().MetersToLongitude(gSigma); // m to radians + if (sigmaRadians > DBL_EPSILON) { + m_weights[1] = 1. / (sigmaRadians*sigmaRadians); // 1/radians^2 + } + } + else if (m_coordTypeBundle == SurfacePoint::Rectangular) { + double sigmakm = gSigma * 0.001; // km + if (sigmakm > DBL_EPSILON) m_weights[1] = 1./ (sigmakm*sigmakm); // 1/km^2 + } + else { + IString msg ="Unknown surface point coordinate type enum [" + + toString(m_coordTypeBundle) + "]." ; + throw IException(IException::Programmer, msg, _FILEINFO_); + } + break; + + case 2: + // Coordinate 2 is either latitudinal radius or rectangular z, both in m + { + double sigmakm = gSigma * .001; // km + m_weights[2] = 1./ (sigmakm*sigmakm); // 1/km^2 + } + break; + + default: + IString msg ="Unknown coordinate index [" + toString(index) + "]." ; + throw IException(IException::Programmer, msg, _FILEINFO_); + } + } + + /** * Resets the number of rejected measures for this BundleControlPoint to zero. * @@ -250,6 +342,73 @@ namespace Isis { } + /** + * Perform the matrix multiplication v2 = alpha ( Q x v1 ). + * + * @param alpha A constant multiplier. + * @param sparseNormals The sparse block normal equations matrix. + * @param v2 The output vector. + * @param Q A sparse block matrix. + * @param v1 A vector. + */ + void BundleControlPoint::productAlphaAV(double alpha, + SparseBlockMatrix &sparseNormals, + LinearAlgebra::Vector &v1) { + + QMapIterator< int, LinearAlgebra::Matrix * > Qit(m_cholmodQMatrix); + + int subrangeStart, subrangeEnd; + + while ( Qit.hasNext() ) { + Qit.next(); + + int columnIndex = Qit.key(); + + subrangeStart = sparseNormals.at(columnIndex)->startColumn(); + subrangeEnd = subrangeStart + Qit.value()->size2(); + + m_nicVector += alpha * prod(*(Qit.value()),subrange(v1,subrangeStart,subrangeEnd)); + } + } + + + /** + * Apply the parameter corrections to the bundle control point. + * + * @param imageSolution Image vector. + * @param factor The unit conversion factor to use on lat and lon rad or x/y/z km. + * @param target The BundleTargetBody. + */ + void BundleControlPoint::applyParameterCorrections(LinearAlgebra::Vector imageSolution, + SparseBlockMatrix &sparseNormals, + const BundleTargetBodyQsp target) { + if (!isRejected()) { + + // subtract product of Q and nj from NIC + productAlphaAV(-1.0, sparseNormals, imageSolution); + + // update adjusted surface point appropriately for the coordinate type + switch (m_coordTypeBundle) { + case SurfacePoint::Latitudinal: + updateAdjustedSurfacePointLatitudinally(target); + break; + case SurfacePoint::Rectangular: + updateAdjustedSurfacePointRectangularly(); + break; + default: + IString msg ="Unknown surface point coordinate type enum [" + + toString(m_coordTypeBundle) + "]." ; + throw IException(IException::Programmer, msg, _FILEINFO_); + } + + // sum and save corrections + m_corrections(0) += m_nicVector[0]; + m_corrections(1) += m_nicVector[1]; + m_corrections(2) += m_nicVector[2]; + } + } + + /** * Accessor for the raw ControlPoint object used for this BundleControlPoint. * @@ -337,10 +496,37 @@ namespace Isis { } - // ??? why bounded vector ??? can we use linear algebra vector ??? + /** + * Accesses BundleControlPoint's coordinate type for reports. + * + * @return @b ControlPoint::CoordinateType The BundleControlPoint's coordinate type. + * See SurfacePoint for the options. + * + * @see ControlPoint::getCoordType() + */ + SurfacePoint::CoordinateType BundleControlPoint::coordTypeReports() const{ + return m_coordTypeReports; + } + + + /** + * Accesses BundleControlPoint's control point coordinate type for the bundle adjustment. + * + * @return @b ControlPoint::CoordinateType The BundleControlPoint's coordinate type. + * See SurfacePoint for the options. + * + * @see ControlPoint::getCoordTypeBundle() + */ + SurfacePoint::CoordinateType BundleControlPoint::coordTypeBundle() const{ + return m_coordTypeBundle; + } + + +// *** TODO *** Need to add bounded vectors to Linear Algebra class /** * Accesses the 3 dimensional ordered vector of correction values associated - * with latitude, longitude, and radius. + * with coord1, coord2, and coord 3 (latitude, longitude, and radius or X, Y, and Z. + * A bounded vector is recommended because the size will always be 3. * * @return @b boost::numeric::ublas::bounded_vector& The vector of correction values. */ @@ -350,20 +536,22 @@ namespace Isis { /** - * Accesses the 3 dimenstional ordered vector of apriori sigmas (apriori - * latitude, apriori longitude, apriori radius). + * Accesses the 3 dimensional ordered vector of apriori sigmas (apriori + * coordinate1, apriori coordinate2, apriori coordinate3). * * @return @b boost::numeric::ublas::bounded_vector& The vector of apriori sigmas. */ boost::numeric::ublas::bounded_vector< double, 3 > &BundleControlPoint::aprioriSigmas() { return m_aprioriSigmas; + // Be careful about units. Latitude and longitude sigmas are in radians. Radius and X/Y/Z are + // meters. } /** - * Accesses the 3 dimenstional ordered vector of adjusted sigmas (adjusted - * latitude, adjusted longitude, adjusted radius). + * Accesses the 3 dimensional ordered vector of adjusted sigmas (adjusted + * coordinate1, adjusted coordinate2, adjusted coordinate3). * * @return @b boost::numeric::ublas::bounded_vector& The vector of adjusted sigmas. */ @@ -374,7 +562,7 @@ namespace Isis { /** * Accesses the 3 dimensional ordered vector of weight values associated - * with latitude, longitude, and radius. + * with coordinate1, coordinate2, and coordinate3. * * @return @b boost::numeric::ublas::bounded_vector& The vector of weight values. */ @@ -406,8 +594,12 @@ namespace Isis { /** * Formats an output summary string for this BundleControlPoint. This string * includes ID, point type, number of rays from non-rejected measures, - * residual RMS, adjusted latitude and longitude (in degrees), adjusted radius - * (in km), and the adjusted sigmas (for latitude, longitude and radius). + * residual RMS, adjusted coordinate1, adjusted coordinate 2, and adjusted + * coordinate 3 followed by the adjusted sigmas. In the case of Latitudinal + * coordinates, the coordinates will be adjusted latitude and longitude (in degrees), + * the adjusted radius (in km), and the adjusted sigmas for latitude, longitude and + * radius all in meters. In the case of Rectangular coordinates, the coordinates + * will be X, Y, Z (in km), and the adjusted sigmas for X, Y, and Z all in meters. * * @param errorPropagation Indicates whether error propagation was selected. * @@ -418,24 +610,32 @@ namespace Isis { int numRays = numberOfMeasures(); // should this depend on the raw point, as written, or this->size()??? int numGoodRays = numRays - numberOfRejectedMeasures(); double ResidualRms = residualRms(); - double lat = m_controlPoint->GetAdjustedSurfacePoint().GetLatitude().degrees(); - double lon = m_controlPoint->GetAdjustedSurfacePoint().GetLongitude().degrees(); - double rad = m_controlPoint->GetAdjustedSurfacePoint().GetLocalRadius().kilometers(); + + // Return generic set of control point coordinates as floating point values + // Be careful because of the potential to confuse units. + SurfacePoint::CoordUnits units = SurfacePoint::Degrees; + if (m_coordTypeReports == SurfacePoint::Rectangular) units = SurfacePoint::Kilometers; + double cpc1 = m_controlPoint->GetAdjustedSurfacePoint().GetCoord(m_coordTypeReports, + SurfacePoint::One, units); + double cpc2 = m_controlPoint->GetAdjustedSurfacePoint().GetCoord(m_coordTypeReports, + SurfacePoint::Two, units); + double cpc3 = m_controlPoint->GetAdjustedSurfacePoint().GetCoord(m_coordTypeReports, + SurfacePoint::Three, SurfacePoint::Kilometers); QString pointType = ControlPoint::PointTypeToString(type()).toUpper(); QString output = QString("%1%2%3 of %4%5%6%7%8%9%10%11\n") - .arg(id(), 16) - .arg(pointType, 15) - .arg(numGoodRays, 5) - .arg(numRays) - .arg(formatValue(ResidualRms, 6, 2)) - .arg(formatValue(lat, 16, 8)) // deg - .arg(formatValue(lon, 16, 8)) // deg - .arg(formatValue(rad, 16, 8)) // km - .arg(formatLatitudeAdjustedSigmaString(16,8,errorPropagation)) // m - .arg(formatLongitudeAdjustedSigmaString(16,8,errorPropagation)) // m - .arg(formatRadiusAdjustedSigmaString(16,8,errorPropagation)); // m + .arg(id(), 16) + .arg(pointType, 15) + .arg(numGoodRays, 5) + .arg(numRays) + .arg(formatValue(ResidualRms, 6, 2)) + .arg(formatValue(cpc1, 16, 8)) // deg km + .arg(formatValue(cpc2, 16, 8)) // deg OR km + .arg(formatValue(cpc3, 16, 8)) // km km + .arg(formatCoordAdjustedSigmaString(SurfacePoint::One, 16, 8, errorPropagation)) // m + .arg(formatCoordAdjustedSigmaString(SurfacePoint::Two, 16, 8, errorPropagation)) // m + .arg(formatCoordAdjustedSigmaString(SurfacePoint::Three, 16, 8, errorPropagation)); // m return output; } @@ -447,11 +647,52 @@ namespace Isis { * @param errorPropagation Indicates whether error propagation was selected. * @param RTM Conversion factor from radians to meters. Used to convert the * latitude and longitude corrections to meters. + * @param solveRadius A flag indicating to solve for each points individual radius. + * When solveRadius is false, the point radius is heavily weighted * * @return @b QString The formatted output detailed string. */ QString BundleControlPoint::formatBundleOutputDetailString(bool errorPropagation, - double RTM, + bool solveRadius) const { + QString output; + + switch (m_coordTypeReports) { + case SurfacePoint::Latitudinal: + output = formatBundleLatitudinalOutputDetailString(errorPropagation, solveRadius); + break; + case SurfacePoint::Rectangular: + output = formatBundleRectangularOutputDetailString(errorPropagation); + break; + default: + IString msg ="Unknown surface point coordinate type enum [" + toString(m_coordTypeBundle) + "]." ; + throw IException(IException::Programmer, msg, _FILEINFO_); + } + return output; + } + + + /** + * Formats a detailed output string table for this Latitudinal BundleControlPoint. + * + * @param errorPropagation Indicates whether error propagation was selected. + * @param RTM Conversion factor from radians to meters. Used to convert the + * latitude and longitude corrections to meters. + * @param solveRadius A flag indicating to solve for each points individual radius. + * When solveRadius is false, the point radius is heavily weighted + * + * @return @b QString The formatted output detailed string. + * + * @internal + * @history 2017-08-24 Debbie A. Cook - Revised units of cor_rad to be km instead of meters + * when outputting latitudinal corrections in degrees. Fixed + * coordinate type for rectPoint to be Displacement::Kilometers + * instead of Distance::Kilometers. Corrected conversions + * of corrections in lat/longitudinal degrees to rectangular meters. + * Fixed output of radius corrections in km. It was outputting + * Z corrections. + */ + QString BundleControlPoint::formatBundleLatitudinalOutputDetailString( + bool errorPropagation, bool solveRadius) const { int numRays = numberOfMeasures(); @@ -460,30 +701,77 @@ namespace Isis { double lon = m_controlPoint->GetAdjustedSurfacePoint().GetLongitude().degrees(); double rad = m_controlPoint->GetAdjustedSurfacePoint().GetLocalRadius().kilometers(); - // ??? corrections is always zero ??? never set in this class ??? + // Use the local radius in meters, rad*1000., to convert radians to meters now instead of the + // target body equatorial radius DAC 09/17/2018 + double rtm = rad * 1000.; + + // Coordinate corrections are currently set in BundleAdjust::applyParameterCorrections in the + // coordTypeBundle coordinates (radians for Latitudinal coordinates and km for Rectangular). // point corrections and initial sigmas - double cor_lat_dd = m_corrections(0) * RAD2DEG; // lat correction, decimal degs - double cor_lon_dd = m_corrections(1) * RAD2DEG; // lon correction, decimal degs - double cor_rad_m = m_corrections(2) * 1000.0; // radius correction, meters + double cor_lat_dd = 0.; // lat correction, decimal degs + double cor_lon_dd = 0.; // lon correction, decimal degs + double cor_rad_km = 0.; // radius correction, kilometers + double cor_lat_m = 0.; // lat correction, meters + double cor_lon_m = 0.; // lon correction, meters + double cor_rad_m = 0.; // radius correction, meters + double latInit = Isis::Null; + double lonInit = Isis::Null; + double radInit = Isis::Null; + if (m_coordTypeBundle == SurfacePoint::Rectangular) { + double x = m_controlPoint->GetAdjustedSurfacePoint().GetX().kilometers(); + double xCor = m_corrections(0); // km + double y = m_controlPoint->GetAdjustedSurfacePoint().GetY().kilometers(); + double yCor = m_corrections(1); // km + double z = m_controlPoint->GetAdjustedSurfacePoint().GetZ().kilometers(); + double zCor = m_corrections(2); // km + + if (!IsSpecial(x) && !IsSpecial(y) && !IsSpecial(z)) { + SurfacePoint rectPoint(Displacement(x - xCor, Displacement::Kilometers), + Displacement(y - yCor, Displacement::Kilometers), + Displacement(z - zCor, Displacement::Kilometers)); + latInit = rectPoint.GetLatitude().degrees(); + lonInit = rectPoint.GetLongitude().degrees(); + radInit = rectPoint.GetLocalRadius().kilometers(); + if (!IsSpecial(lat)) { + cor_lat_dd = (lat - latInit); // degrees + cor_lat_m = cor_lat_dd * DEG2RAD * rtm; + } + if (!IsSpecial(lon)) { + cor_lon_dd = (lon - lonInit); // degrees + cor_lon_m = cor_lon_dd * DEG2RAD * rtm * cos(lat*DEG2RAD); // lon corrections meters + } + if (!IsSpecial(rad)) { + cor_rad_km = rad - radInit; + cor_rad_m = cor_rad_km * 1000.; + } + } + } + else if (m_coordTypeBundle == SurfacePoint::Latitudinal) { + cor_lat_dd = m_corrections(0) * RAD2DEG; // lat correction, decimal degs + cor_lon_dd = m_corrections(1) * RAD2DEG; // lon correction, decimal degs + cor_rad_m = m_corrections(2) * 1000.0; // radius correction, meters - double cor_lat_m = m_corrections(0) * RTM; // lat correction, meters - double cor_lon_m = m_corrections(1) * RTM * cos(lat*DEG2RAD); // lon correction, meters + cor_lat_m = m_controlPoint->GetAdjustedSurfacePoint().LatitudeToMeters(m_corrections(0)); + cor_lon_m = m_controlPoint->GetAdjustedSurfacePoint().LongitudeToMeters(m_corrections(1)); + cor_rad_km = m_corrections(2); - double latInit = Isis::Null; - if (!IsSpecial(lat)) { - latInit = lat - cor_lat_dd; - } + if (!IsSpecial(lat)) { + latInit = lat - cor_lat_dd; + } + if (!IsSpecial(lon)) { + lonInit = lon - cor_lon_dd; + } - double lonInit = Isis::Null; - if (!IsSpecial(lon)) { - lonInit = lon - cor_lon_dd; + if (!IsSpecial(rad)) { + radInit = rad - m_corrections(2); // km + } } - - double radInit = Isis::Null; - if (!IsSpecial(rad)) { - radInit = rad - m_corrections(2); // km + else { + IString msg ="Unknown surface point coordinate type enum [" + + toString(m_coordTypeBundle) + "]." ; + throw IException(IException::Programmer, msg, _FILEINFO_); } QString pointType = ControlPoint::PointTypeToString(type()).toUpper(); @@ -504,29 +792,159 @@ namespace Isis { " (dd/dd/km) (Meters) (Meters)\n"; output += labels; + SurfacePoint::CoordIndex idx = SurfacePoint::One; output += QString(" LATITUDE%1%2%3%4%5%6\n") - .arg(formatValue(latInit, 17, 8)) // deg - .arg(formatValue(cor_lat_dd, 21, 8)) // deg - .arg(formatValue(cor_lat_m, 20, 8)) // m - .arg(formatValue(lat, 20, 8)) // deg - .arg(formatLatitudeAprioriSigmaString(18,8)) // m - .arg(formatLatitudeAdjustedSigmaString(18,8,errorPropagation)); // m - + .arg(formatValue(latInit, 17, 8)) // deg + .arg(formatValue(cor_lat_dd, 21, 8)) // deg + .arg(formatValue(cor_lat_m, 20, 8)) // m + .arg(formatValue(lat, 20, 8)) // deg + .arg(formatCoordAprioriSigmaString(idx, 18,8, true)) // m + .arg(formatCoordAdjustedSigmaString(idx, 18,8,errorPropagation)); // m + + idx = SurfacePoint::Two; output += QString(" LONGITUDE%1%2%3%4%5%6\n") - .arg(formatValue(lonInit, 17, 8)) // deg - .arg(formatValue(cor_lon_dd, 21, 8)) // deg - .arg(formatValue(cor_lon_m, 20, 8)) // m - .arg(formatValue(lon, 20, 8)) // deg - .arg(formatLongitudeAprioriSigmaString(18,8)) // m - .arg(formatLongitudeAdjustedSigmaString(18,8,errorPropagation)); // m - + .arg(formatValue(lonInit, 17, 8)) // deg + .arg(formatValue(cor_lon_dd, 21, 8)) // deg + .arg(formatValue(cor_lon_m, 20, 8)) // m + .arg(formatValue(lon, 20, 8)) // deg + .arg(formatCoordAprioriSigmaString(idx, 18,8, true)) // m + .arg(formatCoordAdjustedSigmaString(idx, 18,8,errorPropagation)); // m + + idx = SurfacePoint::Three; output += QString(" RADIUS%1%2%3%4%5%6\n\n") - .arg(formatValue(radInit, 17, 8)) // km - .arg(formatValue(m_corrections(2), 21, 8)) // km - .arg(formatValue(cor_rad_m, 20, 8)) // m - .arg(formatValue(rad, 20, 8)) // km - .arg(formatRadiusAprioriSigmaString(18,8,solveRadius)) // m - .arg(formatRadiusAdjustedSigmaString(18,8,errorPropagation)); // m + .arg(formatValue(radInit, 17, 8)) // km + .arg(formatValue(cor_rad_km, 21, 8)) // km + .arg(formatValue(cor_rad_m, 20, 8)) // m + .arg(formatValue(rad, 20, 8)) // km + .arg(formatCoordAprioriSigmaString(idx, 18,8, solveRadius)) // m + .arg(formatCoordAdjustedSigmaString(idx, 18,8, errorPropagation)); // m + + return output; + } + + + /** + * Formats a detailed output string table for this Rectangular BundleControlPoint. + * + * @param errorPropagation Indicates whether error propagation was selected. + * + * @return @b QString The formatted output detailed string. + * + * @internal + * @history 2017-08-24 Debbie A. Cook - Corrected units reported in comments to correctly report + * km and also in label line. + */ + QString BundleControlPoint::formatBundleRectangularOutputDetailString + (bool errorPropagation) const { + int numRays = numberOfMeasures(); + int numGoodRays = numRays - numberOfRejectedMeasures(); + double X = m_controlPoint->GetAdjustedSurfacePoint().GetX().kilometers(); + double Y = m_controlPoint->GetAdjustedSurfacePoint().GetY().kilometers(); + double Z = m_controlPoint->GetAdjustedSurfacePoint().GetZ().kilometers(); + + // Coordinate corrections are currently set in applyParameterCorrections. Units depend on + // coordTypeBundle coordinates (radians for Latitudinal coordinates and km for Rectangular). + // point corrections and initial sigmas..... + double cor_X_m = 0.; // X correction, meters + double cor_Y_m = 0.; // Y correction, meters + double cor_Z_m = 0.; // Z correction, meters + double XInit = Isis::Null; + double YInit = Isis::Null; + double ZInit = Isis::Null; + + if (m_coordTypeBundle == SurfacePoint::Latitudinal) { + double lat = m_controlPoint->GetAdjustedSurfacePoint().GetLatitude().degrees(); + double latcor = m_corrections(0) * RAD2DEG; + double lon = m_controlPoint->GetAdjustedSurfacePoint().GetLongitude().degrees(); + double loncor = m_corrections(1) * RAD2DEG; + double rad = m_controlPoint->GetAdjustedSurfacePoint().GetLocalRadius().kilometers(); + double radcor = m_corrections(2); + + if (!IsSpecial(lat) && !IsSpecial(lon) && !IsSpecial(rad)) { + SurfacePoint latPoint(Latitude(lat-latcor, Angle::Degrees), + Longitude(lon-loncor, Angle::Degrees), + Distance(rad-radcor, Distance::Kilometers)); + XInit = latPoint.GetX().kilometers(); + YInit = latPoint.GetY().kilometers(); + ZInit = latPoint.GetZ().kilometers(); + cor_X_m = Isis::Null; + if (!IsSpecial(X)) { + cor_X_m = (X - XInit); // kilometers + } + cor_Y_m = Isis::Null; + if (!IsSpecial(Y)) { + cor_Y_m = (Y - YInit); // kilometers + } + cor_Z_m = Isis::Null; + if (!IsSpecial(Z)) { + cor_Z_m = (Z - ZInit); // kilometers + } + } + } + else if (m_coordTypeBundle == SurfacePoint::Rectangular) { + cor_X_m = m_corrections(0); // X correction, kilometers + cor_Y_m = m_corrections(1); // Y correction, kilometers + cor_Z_m = m_corrections(2); // Z correction, kilometers + if (!IsSpecial(X)) { + XInit = X - m_corrections(0); // km + } + if (!IsSpecial(Y)) { + YInit = Y - m_corrections(1); // km + } + if (!IsSpecial(Z)) { + ZInit = Z - m_corrections(2); // km + } + } + else { + IString msg ="Unknown surface point coordinate type enum [" + + toString(m_coordTypeBundle) + "]." ; + throw IException(IException::Programmer, msg, _FILEINFO_); + } + + QString pointType = ControlPoint::PointTypeToString(type()).toUpper(); + + QString output; + + output = QString(" Label: %1\nStatus: %2\n Rays: %3 of %4\n") + .arg(id()) + .arg(pointType) + .arg(numGoodRays) + .arg(numRays); + + QString labels = + "\n Point Initial Total Final " + " Initial Final\n" + " Coordinate Value Correction Value " + " Accuracy Accuracy\n" + " (km/km/km) (km) (km/km/km) " + " (Meters) (Meters)\n"; + output += labels; + + SurfacePoint::CoordIndex idx = SurfacePoint::One; + output += QString(" BODY-FIXED-X%1%2%3%4%5\n") + .arg(formatValue(XInit, 17, 8)) // km + .arg(formatValue(cor_X_m, 20, 8)) // km + .arg(formatValue(X, 20, 8)) // km + .arg(formatCoordAprioriSigmaString(idx, 18,8, true)) // m + .arg(formatCoordAdjustedSigmaString(idx, 18,8,errorPropagation)); // m + + idx = SurfacePoint::Two; + output += QString(" BODY-FIXED-Y%1%2%3%4%5\n") + .arg(formatValue(YInit, 17, 8)) // km + .arg(formatValue(cor_Y_m, 20, 8)) // km + .arg(formatValue(Y, 20, 8)) // km + .arg(formatCoordAprioriSigmaString(idx, 18, 8, true)) // m + .arg(formatCoordAdjustedSigmaString(idx, 18,8,errorPropagation)); // m + + idx = SurfacePoint::Three; + output += QString(" BODY-FIXED-Z%1%2%3%4%5\n\n") + .arg(formatValue(ZInit, 17, 8)) // km + .arg(formatValue(cor_Z_m, 20, 8)) // km + .arg(formatValue(Z, 20, 8)) // km + // Set solveRadius to true to avoid limiting output information for Z. + // Set radius does not really apply to rectangular coordinates. + .arg(formatCoordAprioriSigmaString(idx, 18,8, true)) // m + .arg(formatCoordAdjustedSigmaString(idx, 18,8,errorPropagation)); // m return output; } @@ -550,27 +968,30 @@ namespace Isis { return output; } - + /** * Formats the apriori sigma value indicated by the given type code. If no * sigma was set, then the string "N/A" will be returned. * - * @param type Integer code that indicates which apriori sigma value will be - * formatted. Latitude=0, Longitude=1, Radius=2. + * @param index CoordIndex Coordinate index One: Latitude or X, Two: Longitude or Y, + * or Three: Radius or Z * @param fieldWidth The return string's field width. * @param precision The precision of the double to be saved off. + * @param solveRadius A flag indicating to solve for each points individual radius. + * When solveRadius is false, the point radius is heavily weighted * * @return @b QString The formatted value, as a string. */ - QString BundleControlPoint::formatAprioriSigmaString(int version, int fieldWidth, - int precision, bool solveRadius) const { + QString BundleControlPoint::formatAprioriSigmaString(SurfacePoint::CoordIndex index, + int fieldWidth, int precision, + bool solveRadius) const { QString aprioriSigmaStr; QString pointType = ControlPoint::PointTypeToString(type()).toUpper(); - if (pointType == "CONSTRAINED"||!solveRadius) { + if (pointType == "CONSTRAINED" || !solveRadius) { pointType = "N/A"; } - double sigma = m_aprioriSigmas[version]; - if (IsSpecial(sigma)) { // if globalAprioriSigma <= 0 (including Isis::NUll), then m_aprioriSigmas = Null + double sigma = m_aprioriSigmas[int(index)]; + if (IsSpecial(sigma)) { // if globalAprioriSigma <= 0 (including Isis::Null), then m_aprioriSigmas = Null aprioriSigmaStr = QString("%1").arg(pointType, fieldWidth); } else { @@ -581,51 +1002,20 @@ namespace Isis { /** - * Formats the apriori latitude sigma value. - * - * @param fieldWidth The return string's field width. - * @param precision The precision of the double to be saved off. - * - * @return @b QString The formatted apriori latitude sigma value, as a string. - * - * @see formatAprioriSigmaString() - */ - QString BundleControlPoint::formatLatitudeAprioriSigmaString(int fieldWidth, - int precision) const { - return formatAprioriSigmaString(0, fieldWidth, precision, true); - } - - - /** - * Formats the apriori longitude sigma value. + * Formats the apriori coordinate 1 (latitude or X) sigma value. * * @param fieldWidth The return string's field width. * @param precision The precision of the double to be saved off. * - * @return @b QString The formatted apriori longitude sigma value, as a string. + * @return @b QString The formatted apriori coordinate 1 sigma value, as a string. * * @see formatAprioriSigmaString() */ - QString BundleControlPoint::formatLongitudeAprioriSigmaString(int fieldWidth, - int precision) const { - return formatAprioriSigmaString(1, fieldWidth, precision, true); - } - - - /** - * Formats the apriori radius sigma value. - * - * @param fieldWidth The return string's field width. - * @param precision The precision of the double to be saved off. - * - * @return @b QString The formatted apriori radius sigma value, as a string. - * - * @see formatAprioriSigmaString() - */ - QString BundleControlPoint::formatRadiusAprioriSigmaString(int fieldWidth, - int precision, - bool solveRadius) const { - return formatAprioriSigmaString(2, fieldWidth, precision, solveRadius); +QString BundleControlPoint::formatCoordAprioriSigmaString(SurfacePoint::CoordIndex index, + int fieldWidth, + int precision, + bool solveRadius) const { + return formatAprioriSigmaString(index, fieldWidth, precision, solveRadius); } @@ -634,15 +1024,16 @@ namespace Isis { * propagation is false or the selected sigma type was set to Null, then only * "N/A" will be returned. * - * @param type Integer code that indicates which apriori sigma value will be - * formatted. Latitude=0, Longitude=1, Radius=2. + * @param index CoordIndex Coordinate index One: Latitude or X, Two: Longitude or Y, + * or Three: Radius or Z * @param fieldWidth The return string's field width. * @param precision The precision of the double to be saved off. * @param errorPropagation Indicates whether error propagation was selected. * * @return @b QString The formatted value, as a string. */ - QString BundleControlPoint::formatAdjustedSigmaString(int type, int fieldWidth, int precision, + QString BundleControlPoint::formatAdjustedSigmaString(SurfacePoint::CoordIndex index, + int fieldWidth, int precision, bool errorPropagation) const { QString adjustedSigmaStr; @@ -651,15 +1042,8 @@ namespace Isis { } else { double sigma = Isis::Null; - if (type == 0) { - sigma = m_controlPoint->GetAdjustedSurfacePoint().GetLatSigmaDistance().meters(); - } - if (type == 1) { - sigma = m_controlPoint->GetAdjustedSurfacePoint().GetLonSigmaDistance().meters(); - } - if (type == 2) { - sigma = m_controlPoint->GetAdjustedSurfacePoint().GetLocalRadiusSigma().meters(); - } + sigma = adjustedSurfacePoint().GetSigmaDistance(m_coordTypeReports, index).meters(); + if (IsSpecial(sigma)) { adjustedSigmaStr = QString("%1").arg("N/A",fieldWidth); } @@ -673,52 +1057,118 @@ namespace Isis { /** - * Formats the adjusted latitude sigma value. + * Formats the adjusted coordinate sigma value. * + * @param index The coordinate index of the sigma to return. * @param fieldWidth The return string's field width. * @param precision The precision of the double to be saved off. * @param errorPropagation Indicates whether error propagation was selected. * - * @return @b QString The formatted adjusted latitude sigma value, as a string. + * @return @b QString The formatted adjusted coordinate sigma value, as a string. * * @see formatAdjustedSigmaString() */ - QString BundleControlPoint::formatLatitudeAdjustedSigmaString(int fieldWidth, int precision, +QString BundleControlPoint::formatCoordAdjustedSigmaString(SurfacePoint::CoordIndex index, + int fieldWidth, int precision, bool errorPropagation) const { - return formatAdjustedSigmaString(0, fieldWidth, precision, errorPropagation); + return formatAdjustedSigmaString(index, fieldWidth, precision, errorPropagation); } /** - * Formats the adjusted longitude sigma value. - * - * @param fieldWidth The return string's field width. - * @param precision The precision of the double to be saved off. - * @param errorPropagation Indicates whether error propagation was selected. - * - * @return @b QString The formatted adjusted longitude sigma value, as a string. - * - * @see formatAdjustedSigmaString() + * Apply the parameter corrections to the bundle control point latitudinally. + * + * @param factor The unit conversion factor to use on lat & lon. Radius is in km & converted to m + * @param target The BundleTargetBody. */ - QString BundleControlPoint::formatLongitudeAdjustedSigmaString(int fieldWidth, int precision, - bool errorPropagation) const { - return formatAdjustedSigmaString(1, fieldWidth, precision, errorPropagation); + void BundleControlPoint::updateAdjustedSurfacePointLatitudinally + (const BundleTargetBodyQsp target) { + SurfacePoint surfacepoint = adjustedSurfacePoint(); + double pointLat = surfacepoint.GetLatitude().degrees(); + double pointLon = surfacepoint.GetLongitude().degrees(); + double pointRad = surfacepoint.GetLocalRadius().meters(); + + // get point parameter corrections + double latCorrection = m_nicVector[0]; + double lonCorrection = m_nicVector[1]; + double radCorrection = m_nicVector[2]; + + // convert to degrees and apply + pointLat += RAD2DEG * latCorrection; + pointLon += RAD2DEG * lonCorrection; + + // Make sure updated values are still in valid range(0 to 360 for lon and -90 to 90 for lat) + if (pointLat < -90.0) { + pointLat = -180.0 - pointLat; + pointLon = pointLon + 180.0; + } + if (pointLat > 90.0) { + pointLat = 180.0 - pointLat; + pointLon = pointLon + 180.0; + } + while (pointLon > 360.0) { + pointLon = pointLon - 360.0; + } + while (pointLon < 0.0) { + pointLon = pointLon + 360.0; + } + + // convert to meters and apply + pointRad += 1000. * radCorrection; + + // ken testing - if solving for target body mean radius, set radius to current + // mean radius value + // Only allow radius options for Latitudinal coordinates + if (target && (target->solveMeanRadius() || target->solveTriaxialRadii()) ) { + if (target->solveMeanRadius()) { + surfacepoint.SetSphericalCoordinates(Latitude(pointLat, Angle::Degrees), + Longitude(pointLon, Angle::Degrees), + target->meanRadius()); + } + else if (target->solveTriaxialRadii()) { + Distance localRadius = target->localRadius(Latitude(pointLat, Angle::Degrees), + Longitude(pointLon, Angle::Degrees)); + surfacepoint.SetSphericalCoordinates(Latitude(pointLat, Angle::Degrees), + Longitude(pointLon, Angle::Degrees), + localRadius); + } + } + else { + surfacepoint.SetSphericalCoordinates(Latitude(pointLat, Angle::Degrees), + Longitude(pointLon, Angle::Degrees), + Distance(pointRad, Distance::Meters)); + } + // Reset the point now that it has been updated + setAdjustedSurfacePoint(surfacepoint); } /** - * Formats the adjusted radius sigma value. - * - * @param fieldWidth The return string's field width. - * @param precision The precision of the double to be saved off. - * @param errorPropagation Indicates whether error propagation was selected. - * - * @return @b QString The formatted adjusted radius sigma value, as a string. - * - * @see formatAdjustedSigmaString() + * Apply the parameter corrections to the bundle control point rectangularly. + * + * @param factor The unit conversion factor to use on the coordinates. */ - QString BundleControlPoint::formatRadiusAdjustedSigmaString(int fieldWidth, int precision, - bool errorPropagation) const { - return formatAdjustedSigmaString(2, fieldWidth, precision, errorPropagation); + void BundleControlPoint::updateAdjustedSurfacePointRectangularly() { + SurfacePoint surfacepoint = adjustedSurfacePoint(); + double pointX = surfacepoint.GetX().meters(); + double pointY = surfacepoint.GetY().meters(); + double pointZ = surfacepoint.GetZ().meters(); + + // get point parameter corrections + double XCorrection = m_nicVector[0]; + double YCorrection = m_nicVector[1]; + double ZCorrection = m_nicVector[2]; + + // Convert corrections to meters and apply + pointX += 1000. * XCorrection; + pointY += 1000. * YCorrection; + pointZ += 1000. * ZCorrection; + + surfacepoint.SetRectangularCoordinates( + Displacement(pointX, Displacement::Meters), + Displacement(pointY, Displacement::Meters), + Displacement(pointZ, Displacement::Meters)); + // Reset the point now that it has been updated + setAdjustedSurfacePoint(surfacepoint); } } diff --git a/isis/src/control/objs/BundleUtilities/BundleControlPoint.h b/isis/src/control/objs/BundleUtilities/BundleControlPoint.h index 7d4e015a98df5e91f99b9eceb3dc083f7c242383..852164af04e4315cb76ebe4f23b28d824b8f3062 100644 --- a/isis/src/control/objs/BundleUtilities/BundleControlPoint.h +++ b/isis/src/control/objs/BundleUtilities/BundleControlPoint.h @@ -36,16 +36,18 @@ namespace Isis { class ControlMeasure; + class LinearAlgebra; + class SparseBlockMatrix; /** - * This class holds information about a control point that BundleAdjust needs to run corretly. + * This class holds information about a control point that BundleAdjust needs to run correctly. * * This class was created to extract functionality from BundleAdjust and wrap a ControlPoint * with the extra necessary information to correctly perform a bundle adjustment. * * Note that only non-ignored control points should be used to construct a BundleControlPoint. * Similarly, a BundleControlPoint should only contain non-ignored control measures. - * + * * @author 2014-05-22 Ken Edmundson * * @internal @@ -67,16 +69,55 @@ namespace Isis { * @history 2016-10-27 Tyler Wilson - Modified formatRadiusAprioriSigmaString, formatAprioriSigmaString, * and formatBundleOutputDetailString to accept a third argument (bool solveRadius) * with a default value = false. References #4317. - */ + * @history 2017-07-26 Debbie A. Cook - Added BundleSettings and metersToRadians as arguments + * to constructor and moved setWeights call from BundleAdjust::init into + * constructor. Added m_bundleControlPointCoordinateType. This option + * determines how control point coordinates are entered into + * BundleControlPoint, interpreted throughout the adjustment, and + * output. The coordinate type needs to be in this class, because + * BundleControlPoints are created without a parent control net and added to + * a control net later. Made format methods generic in regards to coordinate type. + * Added utility method setSigmaWeightFromGlobals. + * Merged methods formatLatitudeAdjustedSigmaString, + * formatLongitudeAdjustedSigmaString, and formatRadiusAdjustedSigmaString + * into a single generic coordinate method with an additional argument + * for the coordinate index. Did a similar merge for the family of + * methods like formatLatitudeAprioriSigmaString. Moved some of the + * functionality from BundleAdjust to this class as a new method + * applyParameterCorrections. Also had to move BundleAdjust method + * productAlphaAV to this class to support applyParameterCorrections. + * References #4649 and #501. + * @history 2017-08-24 Debbie A. Cook - Revised output units to be compatible with output from + * previous versions, corrected units throughout in comments and code. + * Reference #4649 and #501. + * @history 2018-01-05 Debbie A. Cook - Added new members m_coordTypeReports and + * m_coordTypeBundle to copy method. Reference #4649 and #501. + * @history 2018-05-31 Debbie A. Cook - Moved code from BundleAdjust::applyParameterCorrections + * pertaining to updating the adjusted surface point and method productAlphaAv into new + * methods applyParameterCorrections, updateAdjustedSurfacePointLatitudinally, and + * updateAdjustedSurfacePointRectangularly in BundleControlPoint. Reference + * #4649 and #501. + * @history 2018-09-28 Debbie A. Cook - Removed the metersToRadians argument from + * the constructor and from the setWeights method since we are now + * using the local radius of the point to convert lat/lon sigmas + * from meters to radians. References #4649 and #501. + */ class BundleControlPoint : public QVector { public: - BundleControlPoint(ControlPoint *point); // default constructor + // default constructor + BundleControlPoint(BundleSettingsQsp bundleSettings, + ControlPoint *point); + // copy constructor BundleControlPoint(const BundleControlPoint &src); + + //destructor ~BundleControlPoint(); - // copy + // equals operator BundleControlPoint &operator=(const BundleControlPoint &src);// ??? not implemented + + // copy method void copy(const BundleControlPoint &src); // mutators @@ -85,8 +126,17 @@ namespace Isis { void setAdjustedSurfacePoint(SurfacePoint surfacePoint); void setNumberOfRejectedMeasures(int numRejected); void setRejected(bool reject); - void setWeights(const BundleSettingsQsp settings, double metersToRadians); + void setWeights(const BundleSettingsQsp settings); + void setSigmaWeightFromGlobals(double gSigma, int index); + void setSigmaWeightFromGlobals(double gSigma, int index, double cFactor); void zeroNumberOfRejectedMeasures(); + void productAlphaAV(double alpha, + SparseBlockMatrix &sparseNormals, + // boost::numeric::ublas::bounded_vector< double, 3 > &v2, + // SparseBlockRowMatrix &Q, + LinearAlgebra::Vector &v1); + void applyParameterCorrections(LinearAlgebra::Vector imageSolution, + SparseBlockMatrix &sparseNormals, const BundleTargetBodyQsp target); // accessors ControlPoint *rawControlPoint() const; @@ -97,6 +147,8 @@ namespace Isis { SurfacePoint adjustedSurfacePoint() const; QString id() const; ControlPoint::PointType type() const; + SurfacePoint::CoordinateType coordTypeReports() const; + SurfacePoint::CoordinateType coordTypeBundle() const; boost::numeric::ublas::bounded_vector< double, 3 > &corrections(); boost::numeric::ublas::bounded_vector< double, 3 > &aprioriSigmas(); boost::numeric::ublas::bounded_vector< double, 3 > &adjustedSigmas(); @@ -106,22 +158,25 @@ namespace Isis { // string format methods QString formatBundleOutputSummaryString(bool errorPropagation) const; - QString formatBundleOutputDetailString(bool errorPropagation, double RTM, bool solveRadius=false) const; + QString formatBundleOutputDetailString(bool errorPropagation, bool solveRadius=false) const; + QString formatBundleLatitudinalOutputDetailString(bool errorPropagation, + bool solveRadius=false) const; + QString formatBundleRectangularOutputDetailString(bool errorPropagation) const; QString formatValue(double value, int fieldWidth, int precision) const; - QString formatAprioriSigmaString(int type, int fieldWidth, int precision, bool solveRadius=false) const; - QString formatLatitudeAprioriSigmaString(int fieldWidth, int precision) const; - QString formatLongitudeAprioriSigmaString(int fieldWidth, int precision) const; - QString formatRadiusAprioriSigmaString(int fieldWidth, int precision, bool solveRadius=false) const; - QString formatAdjustedSigmaString(int type, int fieldWidth, int precision, + QString formatAprioriSigmaString(SurfacePoint::CoordIndex index, int fieldWidth, + int precision, bool solveRadius=false) const; + QString formatCoordAprioriSigmaString(SurfacePoint::CoordIndex index, int fieldWidth, + int precision, bool solveRadius=false) const; + QString formatAdjustedSigmaString(SurfacePoint::CoordIndex, int fieldWidth, int precision, bool errorPropagation) const; - QString formatLatitudeAdjustedSigmaString(int fieldWidth, int precision, + QString formatCoordAdjustedSigmaString(SurfacePoint::CoordIndex, int fieldWidth, int precision, bool errorPropagation) const; - QString formatLongitudeAdjustedSigmaString(int fieldWidth, int precision, - bool errorPropagation) const; - QString formatRadiusAdjustedSigmaString(int fieldWidth, int precision, - bool errorPropagation) const; private: + // methods + void updateAdjustedSurfacePointLatitudinally(const BundleTargetBodyQsp target); + void updateAdjustedSurfacePointRectangularly(); + //!< pointer to the control point object this represents ControlPoint *m_controlPoint; @@ -137,6 +192,9 @@ namespace Isis { boost::numeric::ublas::bounded_vector m_nicVector; //! The CholMod matrix associated with this point SparseBlockRowMatrix m_cholmodQMatrix; + //! BundleControlPoint coordinate type + SurfacePoint::CoordinateType m_coordTypeReports; + SurfacePoint::CoordinateType m_coordTypeBundle; }; // typedefs diff --git a/isis/src/control/objs/BundleUtilities/BundleUtilities.truth b/isis/src/control/objs/BundleUtilities/BundleUtilities.truth index 84860c9ab7b55de68395ceaf66a422859edc05a7..e898b234ac4a64243ba0482d2014fa3c0e4da886 100644 --- a/isis/src/control/objs/BundleUtilities/BundleUtilities.truth +++ b/isis/src/control/objs/BundleUtilities/BundleUtilities.truth @@ -547,7 +547,8 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX Testing BundleControlPoint... -Create FreePoint with free point containing 2 measures... (note that first measure is ignored, second measure is not ignored) +BCP test 1 - Create FreePoint with free point containing 2 measures (note that first measure is ignored, second measure is not ignored) + and no apriori or adjusted coordinate values or sigmas set... Type of BundleControlPoint 1: 2 Set BundleControlPoint 1 to rejected - is rejected? "Yes" Set BundleControlPoint 1 to non-rejected - is rejected? "No" @@ -583,22 +584,7 @@ Coordinate Value Correction Correction -Modify FreePoint - setAdjustedSurfacePoint(0,0,10) and addMeasure() - FreePoint FREE 2 of 2 3.54 0.00000000 0.00000000 0.01000000 N/A N/A N/A - - Label: FreePoint -Status: FREE - Rays: 2 of 2 - - Point Initial Total Total Final Initial Final -Coordinate Value Correction Correction Value Accuracy Accuracy - (dd/dd/km) (dd/dd/km) (Meters) (dd/dd/km) (Meters) (Meters) - LATITUDE 0.00000000 0.00000000 0.00000000 0.00000000 FREE N/A - LONGITUDE 0.00000000 0.00000000 0.00000000 0.00000000 FREE N/A - RADIUS 0.01000000 0.00000000 0.00000000 0.01000000 N/A N/A - - -Modify FreePoint - setWeights() - solveRadius=false +BCP test 2 - Modify FreePoint - setAdjustedSurfacePoint(0,0,10) and addMeasure() FreePoint FREE 2 of 2 3.54 0.00000000 0.00000000 0.01000000 N/A N/A N/A Label: FreePoint @@ -623,7 +609,8 @@ qMatrix: Residual rms: 3.53553 -Modify FreePoint - setWeights() - solveRadius=true, apriori lat/lon/rad <= 0 +BCP test 3 - Create FreePoint - identical to previous, but with solveRadius=true + and apriori lat/lon/rad <= 0. Test adding a measure to a BundleControlPoint. FreePoint FREE 2 of 2 3.54 0.00000000 0.00000000 0.01000000 N/A N/A N/A Label: FreePoint @@ -635,13 +622,14 @@ Coordinate Value Correction Correction (dd/dd/km) (dd/dd/km) (Meters) (dd/dd/km) (Meters) (Meters) LATITUDE 0.00000000 0.00000000 0.00000000 0.00000000 FREE N/A LONGITUDE 0.00000000 0.00000000 0.00000000 0.00000000 FREE N/A - RADIUS 0.01000000 0.00000000 0.00000000 0.01000000 N/A N/A + RADIUS 0.01000000 0.00000000 0.00000000 0.01000000 FREE N/A aprioriSigmas: "N/A" "N/A" "N/A" -weights: 0 0 1e+50 +weights: 0 0 0 -Modify FreePoint - setWeights() - solveRadius=true, apriori lat/lon/rad > 0 +BCP test 4 - Create FreePoint - solveRadius=true, apriori lat/lon/rad > 0 + from globals - coordinate type = Latitudinal FreePoint FREE 2 of 2 3.54 0.00000000 0.00000000 0.01000000 N/A N/A N/A Label: FreePoint @@ -663,7 +651,7 @@ Raw control point equal to original? "Yes" Raw control point is rejected? "No" Adjusted SurfacePoint (Lat, Lon, Rad) = "0.0" "0.0" "10.0" -Create FixedPoint from empty fixed point, adjusted surface point (90, 180, 10)... +BCP test 5 - Create FixedPoint from empty fixed point, solveRadius = F adjusted surface point (90, 180, 10)... FixedPoint FIXED 0 of 0 0.00 90.00000000 180.00000000 0.01000000 N/A N/A N/A Label: FixedPoint @@ -678,7 +666,8 @@ Coordinate Value Correction Correction RADIUS 0.01000000 0.00000000 0.00000000 0.01000000 N/A N/A -Modify FixedPoint - setWeights() +BCP test 6 - Create FixedPoint from empty fixed point, solveRadius = True + adjusted surface point (90, 180, 10)... FixedPoint FIXED 0 of 0 0.00 90.00000000 180.00000000 0.01000000 N/A N/A N/A Label: FixedPoint @@ -690,28 +679,13 @@ Coordinate Value Correction Correction (dd/dd/km) (dd/dd/km) (Meters) (dd/dd/km) (Meters) (Meters) LATITUDE 90.00000000 0.00000000 0.00000000 90.00000000 FIXED N/A LONGITUDE 180.00000000 0.00000000 0.00000000 180.00000000 FIXED N/A - RADIUS 0.01000000 0.00000000 0.00000000 0.01000000 N/A N/A + RADIUS 0.01000000 0.00000000 0.00000000 0.01000000 FIXED N/A aprioriSigmas: "NULL" "NULL" "NULL" weights: 1e+50 1e+50 1e+50 -Create ConstrainedPoint from empty constrained point, surface point (0, 0, 10)... -ConstrainedPoint CONSTRAINED 0 of 0 0.00 0.00000000 0.00000000 0.01000000 N/A N/A N/A - - Label: ConstrainedPoint -Status: CONSTRAINED - Rays: 0 of 0 - - Point Initial Total Total Final Initial Final -Coordinate Value Correction Correction Value Accuracy Accuracy - (dd/dd/km) (dd/dd/km) (Meters) (dd/dd/km) (Meters) (Meters) - LATITUDE 0.00000000 0.00000000 0.00000000 0.00000000 N/A N/A - LONGITUDE 0.00000000 0.00000000 0.00000000 0.00000000 N/A N/A - RADIUS 0.01000000 0.00000000 0.00000000 0.01000000 N/A N/A - - -Modify ConstrainedPoint - setWeights() - solveRadius=false +BCP test 7 - Create ConstrainedPoint with solveRadius=false and adjusted surface point (0, 0, 10), no constraints set, coordType=Latitudinal ... ConstrainedPoint CONSTRAINED 0 of 0 0.00 0.00000000 0.00000000 0.01000000 N/A N/A N/A Label: ConstrainedPoint @@ -729,7 +703,8 @@ Coordinate Value Correction Correction aprioriSigmas: "NULL" "NULL" "NULL" weights: 0 0 1e+50 -Modify ConstrainedPoint - setWeights() - no constraints, solveRadius=true, apriori lat/lon/rad <= 0 +BCP test 8 - Create ConstrainedPoint - no constraints, solveRadius=true, apriori lat/lon/rad <= 0, + and adjustedsurface point (0, 0, 10) ConstrainedPoint CONSTRAINED 0 of 0 0.00 0.00000000 0.00000000 0.01000000 N/A N/A N/A Label: ConstrainedPoint @@ -745,9 +720,9 @@ Coordinate Value Correction Correction aprioriSigmas: "NULL" "NULL" "NULL" -weights: 0 0 1e+50 +weights: 0 0 0 -Modify ConstrainedPoint - setWeights() - no constraints, solveRadius=true, apriori lat/lon/rad > 0 +BCP test 9 - Create ConstrainedPoint - no constraints, solveRadius=true, apriori lat/lon/rad > 0 (valid global sigmas) ConstrainedPoint CONSTRAINED 0 of 0 0.00 0.00000000 0.00000000 0.01000000 N/A N/A N/A Label: ConstrainedPoint @@ -766,8 +741,9 @@ aprioriSigmas: "2.0" "3.0" "4.0" weights: 25 11.1111 62500 -Create ConstrainedPoint from constrained point with adjusted surface point (32, 120, 1000)... -ConstrainedPoint CONSTRAINED 0 of 0 0.00 32.00000000 120.00000000 1.00000000 28.65696503 26.45751316 38.45488734 +BCP test 10 - Create ConstrainedPoint from constrained point with adjusted + pt (32, 120, 1000) & apriori pt with constraints from covar, solveRadius=F... +ConstrainedPoint CONSTRAINED 0 of 0 0.00 32.00000000 120.00000000 1.00000000 28.65696495 26.45751311 38.45488734 Label: ConstrainedPoint Status: CONSTRAINED @@ -776,13 +752,14 @@ Status: CONSTRAINED Point Initial Total Total Final Initial Final Coordinate Value Correction Correction Value Accuracy Accuracy (dd/dd/km) (dd/dd/km) (Meters) (dd/dd/km) (Meters) (Meters) - LATITUDE 32.00000000 0.00000000 0.00000000 32.00000000 N/A 28.65696503 - LONGITUDE 120.00000000 0.00000000 0.00000000 120.00000000 N/A 26.45751316 + LATITUDE 32.00000000 0.00000000 0.00000000 32.00000000 28.65696494 28.65696495 + LONGITUDE 120.00000000 0.00000000 0.00000000 120.00000000 26.45751311 26.45751311 RADIUS 1.00000000 0.00000000 0.00000000 1.00000000 N/A 38.45488734 -Modify ConstrainedPoint - setWeights() - solveRadius=t, lat/lon/rad constrained -ConstrainedPoint CONSTRAINED 0 of 0 0.00 32.00000000 120.00000000 1.00000000 28.65696503 26.45751316 38.45488734 +BCP test 11 - Create ConstrainedPoint from constrained point with adjusted surface pt (32, 120, 1000) + & apriori pt with constraints from covar, solveRadius=T... +ConstrainedPoint CONSTRAINED 0 of 0 0.00 32.00000000 120.00000000 1.00000000 28.65696495 26.45751311 38.45488734 Label: ConstrainedPoint Status: CONSTRAINED @@ -791,15 +768,15 @@ Status: CONSTRAINED Point Initial Total Total Final Initial Final Coordinate Value Correction Correction Value Accuracy Accuracy (dd/dd/km) (dd/dd/km) (Meters) (dd/dd/km) (Meters) (Meters) - LATITUDE 32.00000000 0.00000000 0.00000000 32.00000000 28.65696494 28.65696503 - LONGITUDE 120.00000000 0.00000000 0.00000000 120.00000000 26.45751311 26.45751316 + LATITUDE 32.00000000 0.00000000 0.00000000 32.00000000 28.65696494 28.65696495 + LONGITUDE 120.00000000 0.00000000 0.00000000 120.00000000 26.45751311 26.45751311 RADIUS 1.00000000 0.00000000 0.00000000 1.00000000 38.45488734 38.45488734 aprioriSigmas: "28.65696494252" "26.457513107566" "38.454887341483" weights: 1217.7 1027.41 676.234 -Create copy of FreePoint using copy constructor... +BCP test 12 - Create copy of FreePoint using copy constructor... FreePoint FREE 2 of 2 3.54 0.00000000 0.00000000 0.01000000 N/A N/A N/A Output for formatBundleOutputDetailString(...) with solveForRadius = false: @@ -815,7 +792,7 @@ Coordinate Value Correction Correction RADIUS 0.01000000 0.00000000 0.00000000 0.01000000 4.00000000 N/A -Output for formatBundleOutputDetailString(...) with solveForRadius = true: +BCP test 13 - Output for formatBundleOutputDetailString(...) with solveForRadius = true: Label: FreePoint Status: FREE Rays: 2 of 2 @@ -829,7 +806,7 @@ Coordinate Value Correction Correction -Overwrite existing object with FixedPoint information... +BCP test 14 - Overwrite existing object with FixedPoint information... FixedPoint FIXED 0 of 0 0.00 90.00000000 180.00000000 0.01000000 N/A N/A N/A Label: FixedPoint @@ -845,6 +822,115 @@ Coordinate Value Correction Correction +BCP test 15 - Coordtype=Rect, Free, solveRad=F + FreePoint FREE 1 of 1 3.54 0.01000000 0.00000000 0.00000000 N/A N/A N/A + + Label: FreePoint +Status: FREE + Rays: 1 of 1 + + Point Initial Total Final Initial Final + Coordinate Value Correction Value Accuracy Accuracy + (km/km/km) (km) (km/km/km) (Meters) (Meters) + BODY-FIXED-X 0.01000000 0.00000000 0.01000000 FREE N/A + BODY-FIXED-Y 0.00000000 0.00000000 0.00000000 FREE N/A + BODY-FIXED-Z 0.00000000 0.00000000 0.00000000 FREE N/A + + +weights: 0 0 0 + +BCP test 16 - Coordtype=Rect, Free, solveRad=T + FreePoint FREE 1 of 1 3.54 0.01000000 0.00000000 0.00000000 N/A N/A N/A + + Label: FreePoint +Status: FREE + Rays: 1 of 1 + + Point Initial Total Final Initial Final + Coordinate Value Correction Value Accuracy Accuracy + (km/km/km) (km) (km/km/km) (Meters) (Meters) + BODY-FIXED-X 0.01000000 0.00000000 0.01000000 2.00000000 N/A + BODY-FIXED-Y 0.00000000 0.00000000 0.00000000 3.00000000 N/A + BODY-FIXED-Z 0.00000000 0.00000000 0.00000000 4.00000000 N/A + + +weights: 250000 111111 62500 + + +BCP test 17 - Coordtype=Rect, Fixed, solveRad=F + FixedPoint FIXED 0 of 0 0.00 0.00000000 0.00000000 1.00000000 N/A N/A N/A + + Label: FixedPoint +Status: FIXED + Rays: 0 of 0 + + Point Initial Total Final Initial Final + Coordinate Value Correction Value Accuracy Accuracy + (km/km/km) (km) (km/km/km) (Meters) (Meters) + BODY-FIXED-X 0.00000000 0.00000000 0.00000000 FIXED N/A + BODY-FIXED-Y 0.00000000 0.00000000 0.00000000 FIXED N/A + BODY-FIXED-Z 1.00000000 0.00000000 1.00000000 FIXED N/A + + +weights: 1e+50 1e+50 1e+50 + + +BCP test 18 - Create ConstrainedPoint with solveRadius=false and adjusted surface point (0, 0, 1000), no constraints set, and coordType = Rect ... +ConstrainedPoint CONSTRAINED 0 of 0 0.00 0.00000000 0.00000000 1.00000000 N/A N/A N/A + + Label: ConstrainedPoint +Status: CONSTRAINED + Rays: 0 of 0 + + Point Initial Total Final Initial Final + Coordinate Value Correction Value Accuracy Accuracy + (km/km/km) (km) (km/km/km) (Meters) (Meters) + BODY-FIXED-X 0.00000000 0.00000000 0.00000000 N/A N/A + BODY-FIXED-Y 0.00000000 0.00000000 0.00000000 N/A N/A + BODY-FIXED-Z 1.00000000 0.00000000 1.00000000 N/A N/A + + +aprioriSigmas: "NULL" "NULL" "NULL" +weights: 0 0 0 + +BCP test 19 - Create ConstrainedPoint with solveRadius=false and adjusted surface point (0, 0, 1000), valid globals, and coordType = Rect ... +ConstrainedPoint CONSTRAINED 0 of 0 0.00 0.00000000 0.00000000 1.00000000 N/A N/A N/A + + Label: ConstrainedPoint +Status: CONSTRAINED + Rays: 0 of 0 + + Point Initial Total Final Initial Final + Coordinate Value Correction Value Accuracy Accuracy + (km/km/km) (km) (km/km/km) (Meters) (Meters) + BODY-FIXED-X 0.00000000 0.00000000 0.00000000 2.00000000 N/A + BODY-FIXED-Y 0.00000000 0.00000000 0.00000000 3.00000000 N/A + BODY-FIXED-Z 1.00000000 0.00000000 1.00000000 4.00000000 N/A + + +aprioriSigmas: "2.0" "3.0" "4.0" +weights: 250000 111111 62500 + +BCP test 20 - Create ConstrainedPoint from constrained point with adjusted + pt (32, 120, 1000) & apriori pt from Test 10 with constraints from covar, solveRadius=F, +coordType=Rectangular... + +ConstrainedPoint CONSTRAINED 0 of 0 0.00 -0.42402405 0.73443119 0.52991926 10.00000000 50.00000000 20.00000000 + + Label: ConstrainedPoint +Status: CONSTRAINED + Rays: 0 of 0 + + Point Initial Total Final Initial Final + Coordinate Value Correction Value Accuracy Accuracy + (km/km/km) (km) (km/km/km) (Meters) (Meters) + BODY-FIXED-X -0.42402405 0.00000000 -0.42402405 10.00000000 10.00000000 + BODY-FIXED-Y 0.73443119 0.00000000 0.73443119 50.00000000 50.00000000 + BODY-FIXED-Z 0.52991926 0.00000000 0.52991926 20.00000000 20.00000000 + + +BCP test 21 - Test invalid coordinate type + XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX diff --git a/isis/src/control/objs/BundleUtilities/unitTest.cpp b/isis/src/control/objs/BundleUtilities/unitTest.cpp index f2c38bd7cdb3484fb57db027218211dba540c9eb..e33ce93a3ef468c45cec738ee556b2a453b52b81 100755 --- a/isis/src/control/objs/BundleUtilities/unitTest.cpp +++ b/isis/src/control/objs/BundleUtilities/unitTest.cpp @@ -1,15 +1,3 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - #include "Angle.h" #include "BundleControlPoint.h" #include "BundleImage.h" @@ -20,6 +8,7 @@ #include "BundleSettings.h" #include "BundleTargetBody.h" #include "Camera.h" +#include "ControlNet.h" #include "ControlPoint.h" #include "ControlMeasure.h" #include "Distance.h" @@ -36,6 +25,18 @@ #include "Target.h" #include "XmlStackedHandlerReader.h" +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + using namespace std; using namespace Isis; @@ -48,8 +49,27 @@ void printXml(const BundleObservationSolveSettings &); * @author 2014 Jeannie Backer * * @internal + * @history 2018-07-03 Debbie A Cook - Removed target radii. References #5457. * @history 2014-12-11 - Original version. - * @history 2018-07-03 Debbie A Cook - Removed target radii. References #5457. + * @history 2018-09-06 Debbie A. Cook - Merged dev into BundleXYZ branch + * Original branch history entry on 2017-06-26 + * Updated to reflect changes made to BundleControlPoint. + * Some tests were no longer valid and new tests were added to exercise + * the new option of adjusting in Rectangular coordinates. The + * Latitudinal covariance was being populated only along the diagonal + * (using the latitudinal sigmas). This produced inaccurate results. + * Now it is created by converting the rectangular covariance + * matrix to latitudinal. References #4649 and #501. + * @history 2018 -09-06 Debbie A. Cook - Merged dev into BundleXYZ branch + * Original branch history entry on 2017-11-29 - Updated to reflect + * changes made to units of covariance matrix in SurfacePoint methods + * and removal of SurfacePoint::SetRadii method. + * @history 2018-09-28 Debbie A. Cook - Removed metersToRadians argument from + * constructor because we are now using the local radius instead of + * the target body equatorial radius to convert meters to radians. To + * work, the apriori coordinates must be set. Some of the tests do not + * require the apriori coordinates to be set, so those tests were + * modified. */ namespace Isis { class XmlHandlerTester : public BundleObservationSolveSettings { @@ -99,6 +119,16 @@ namespace Isis { * @history 2016-12-01 Ian Humphrey - Added extra qDebug() stream so the "apply param * corrections successful?" string will be in the unitTest output. * @history 2017-04-24 Ian Humphrey - Replaced pvlObject() with XML save(). Fixes #4797. + * @history 2017-03-05 Debbie A. Cook - updated to conform to changes made to + * BundleControlPointConstructor. Fixed test + * "Modify FreePoint - setWeights() - solveRadius=true, apriori lat/lon/rad <= 0" + * to output radius type as free instead of N/A under Inital Accuracy column and + * fixed weight value to be 0. Corrections were made by creating a new contol + * point when the settings were changed instead of just calling setWeights. + * Deleted tests "Modified FreePoint - setWeights, "Modify FixedPoint - + * setWeights() and ModifyConstrainedPoint - setWeights()" since + * setWeights is always called in the constructor now. References + * #4649 and #501 */ int main(int argc, char *argv[]) { Preference::Preferences(true); @@ -522,12 +552,12 @@ int main(int argc, char *argv[]) { catch (IException &e) { e.print(); } - qDebug() << "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"; qDebug() << ""; qDebug() << "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"; qDebug() << "Testing BundleObservationVector..."; qDebug() << ""; + /* #if 0 TEST COVERAGE (SCOPE) FOR THIS SOURCE FILE: 21% Need: @@ -557,6 +587,7 @@ int main(int argc, char *argv[]) { 9) getObsByCubeSerialNumber - map.contains(sn) == false #endif + */ BundleObservationVector bov; BundleSettingsQsp bundleSettings = BundleSettingsQsp(new BundleSettings); // BundleObservation *obs1 = bov.addNew(bi2, "obs1", "InstrumentIdBOV", bundleSettings); @@ -582,8 +613,11 @@ int main(int argc, char *argv[]) { #if 0 TEST COVERAGE (SCOPE) FOR THIS SOURCE FILE: 100% #endif - qDebug() << "Create FreePoint with free point containing 2 measures..." - << "(note that first measure is ignored, second measure is not ignored)"; + // #1 Test free point with default settings (solveRadius=false), apriori coordinates set, but no + // sigmas (other settings: observation mode = false, update =false, errorProp = false) + qDebug() << "BCP test 1 - Create FreePoint with free point containing 2 measures " + "(note that first measure is ignored, second measure is not ignored)"; + qDebug() << " and no apriori or adjusted coordinate values or sigmas set..."; ControlPoint *freePoint = new ControlPoint("FreePoint"); ControlMeasure *cm1 = new ControlMeasure; cm1->SetCubeSerialNumber("Ignored"); @@ -595,9 +629,10 @@ int main(int argc, char *argv[]) { cm2->SetCoordinate(1.0, 2.0); cm2->SetResidual(-3.0, 4.0); freePoint->Add(cm2); - BundleControlPoint bcp1(freePoint); +// Moved these lines up from below (DAC 2-25-2017) + BundleSettingsQsp settings = BundleSettingsQsp(new BundleSettings); + BundleControlPoint bcp1(settings, freePoint); bool errorProp = false; - double radiansToMeters = 10.0; qDebug() << "Type of BundleControlPoint 1:" << bcp1.type(); @@ -614,18 +649,21 @@ int main(int argc, char *argv[]) { bcp1.zeroNumberOfRejectedMeasures(); qDebug() << "Zero out number of rejected measures:" << bcp1.numberOfRejectedMeasures(); - // ??? these print outs are not pretty... fix??? + // ??? these print outs are not pretty... fix??? qDebug().noquote() << bcp1.formatBundleOutputSummaryString(errorProp); - // ??? these print outs are not pretty... fix??? - qDebug().noquote() << bcp1.formatBundleOutputDetailString(errorProp, radiansToMeters); + // ??? these print outs are not pretty... fix??? improved somewhat 6-9-2017 + qDebug().noquote() << bcp1.formatBundleOutputDetailString(errorProp); + // Test free point. Settings same, but errorProp = true) errorProp = true; // ??? these print outs are not pretty... fix??? qDebug().noquote() << bcp1.formatBundleOutputSummaryString(errorProp); // ??? these print outs are not pretty... fix??? - qDebug().noquote() << bcp1.formatBundleOutputDetailString(errorProp, radiansToMeters); + qDebug().noquote() << bcp1.formatBundleOutputDetailString(errorProp); qDebug() << ""; - qDebug() << "Modify FreePoint - setAdjustedSurfacePoint(0,0,10) and addMeasure()"; +// #2 Same as test 1, but assign coordinate values (0., 0., 10.) to adjusted surface points of FREE +// point with solve radius still false -- radius weight is fixed (1.0e+50). Other coordinates are free + qDebug() << "BCP test 2 - Modify FreePoint - setAdjustedSurfacePoint(0,0,10) and addMeasure()"; SurfacePoint sp1(Latitude(0.0, Angle::Degrees), Longitude(0.0, Angle::Degrees), Distance(10.0, Distance::Meters)); @@ -638,15 +676,23 @@ int main(int argc, char *argv[]) { // ??? these print outs are not pretty... fix??? qDebug().noquote() << bcp1.formatBundleOutputSummaryString(errorProp); // ??? these print outs are not pretty... fix??? - qDebug().noquote() << bcp1.formatBundleOutputDetailString(errorProp, radiansToMeters); - - qDebug() << "Modify FreePoint - setWeights() - solveRadius=false"; - // default solveRadius=false - BundleSettingsQsp settings = BundleSettingsQsp(new BundleSettings); - double metersToRadians = 1.0 / radiansToMeters; - bcp1.setWeights(settings, metersToRadians); - qDebug().noquote() << bcp1.formatBundleOutputSummaryString(errorProp); - qDebug().noquote() << bcp1.formatBundleOutputDetailString(errorProp, radiansToMeters); + qDebug().noquote() << bcp1.formatBundleOutputDetailString(errorProp); + + // Same but look at values of aprioriSigmas, weights, corrections, etc. + // qDebug() << "Modify FreePoint - setWeights() - solveRadius=false"; + // Deleted summary and detail output here since it is duplicated now that the BCP and the + // constructor always calls setWeights now.; +// Before the change, test2 checked default settings and default weights. Omitted test checked +// BCP creation using a blank settings (equivalent to no settings) and a setWeights call that only +// specifies solveRadius to false, which is the same as the default. +// default solveRadius=false + + // These now commented lines were moved to before creation of bcp1 and + // setWeights now happens in BundleControlPoint constructor (DAC 2-25-2017) + // BundleSettingsQsp settings = BundleSettingsQsp(new BundleSettings); + // double metersToRadians = 1.0 / radiansToMeters; + // bcp1.setWeights(settings, metersToRadians); + // qDebug().noquote() << bcp1.formatBundleOutputDetailString(errorProp, radiansToMeters); boost::numeric::ublas::bounded_vector< double, 3 > aprioriSigmas = bcp1.aprioriSigmas(); boost::numeric::ublas::bounded_vector< double, 3 > weights = bcp1.weights(); //??? never set 000??? init to 1.0e+50??? @@ -672,14 +718,29 @@ int main(int argc, char *argv[]) { qDebug() << "Residual rms:" << bcp1.residualRms(); qDebug() << ""; - - qDebug() << "Modify FreePoint - setWeights() - solveRadius=true, apriori lat/lon/rad <= 0"; - settings->setSolveOptions(false, false, false, true, Isis::Null); - bcp1.setWeights(settings, metersToRadians); - qDebug().noquote() << bcp1.formatBundleOutputSummaryString(errorProp); - qDebug().noquote() << bcp1.formatBundleOutputDetailString(errorProp, radiansToMeters); - aprioriSigmas = bcp1.aprioriSigmas(); - weights = bcp1.weights(); +// end test 2 + + // #3 Test free point with solveRadius=true (default), no corrections or valid sigmas + qDebug() << "BCP test 3 - Create FreePoint - identical to previous, but with solveRadius=true"; + qDebug() << " and apriori lat/lon/rad <= 0. Test adding a measure to a BundleControlPoint."; +// Create a new BundleControlPoint like the previous one with settings to indicate radius is free + settings->setSolveOptions(false, false, false, true, SurfacePoint::Latitudinal, + SurfacePoint::Latitudinal, Isis::Null); + BundleControlPoint bcp1a(settings, freePoint); + bcp1a.setAdjustedSurfacePoint(sp1); + BundleMeasure bcm1a = *(bcp1a.addMeasure(cm1)); +// Note: This test was abusing the setWeights method of BundleControlPoint. +// It was using setWeights to update bcp1 with new BundleSettings; in particular, +// it was changing the solveRadius bool from false to true. This did not work +// properly because setWeights was designed to update weights after they were +// initialized by the constructor. The radius weight was set to 1.0e+50 when bcp1 +// was created with solveRadius set to false. When setWeights was used to update +// the settings, the radius weight was not changed back. setWeights should NOT +// be used to update BundleSettings. This is likely only a test issue. + qDebug().noquote() << bcp1a.formatBundleOutputSummaryString(errorProp); + qDebug().noquote() << bcp1a.formatBundleOutputDetailString(errorProp, true); + aprioriSigmas = bcp1a.aprioriSigmas(); + weights = bcp1a.weights(); qDebug() << "aprioriSigmas: " << (Isis::IsSpecial(aprioriSigmas[0]) ? "N/A" : Isis::toString(aprioriSigmas[0])) << (Isis::IsSpecial(aprioriSigmas[1]) ? "N/A" : Isis::toString(aprioriSigmas[1])) @@ -687,13 +748,19 @@ int main(int argc, char *argv[]) { qDebug() << "weights: " << weights[0] << weights[1] << weights[2]; qDebug() << ""; - qDebug() << "Modify FreePoint - setWeights() - solveRadius=true, apriori lat/lon/rad > 0"; - settings->setSolveOptions(false, false, false, true, 2.0, 3.0, 4.0); - bcp1.setWeights(settings, metersToRadians); - qDebug().noquote() << bcp1.formatBundleOutputSummaryString(errorProp); - qDebug().noquote() << bcp1.formatBundleOutputDetailString(errorProp, radiansToMeters); - aprioriSigmas = bcp1.aprioriSigmas(); - weights = bcp1.weights(); +// #4 Test with global sigmas now. Everything else is the same as test #3. + qDebug() << "BCP test 4 - Create FreePoint - solveRadius=true, apriori lat/lon/rad > 0 "; + qDebug() << " from globals - coordinate type = Latitudinal"; + settings->setSolveOptions(false, false, false, true, SurfacePoint::Latitudinal, + SurfacePoint::Latitudinal, 2.0, 3.0, 4.0); + freePoint->SetAprioriSurfacePoint(sp1); + BundleControlPoint bcp1b(settings, freePoint); + bcp1b.setAdjustedSurfacePoint(sp1); + BundleMeasure bcm1b = *(bcp1b.addMeasure(cm1)); + qDebug().noquote() << bcp1b.formatBundleOutputSummaryString(errorProp); + qDebug().noquote() << bcp1b.formatBundleOutputDetailString(errorProp); + aprioriSigmas = bcp1b.aprioriSigmas(); + weights = bcp1b.weights(); qDebug() << "aprioriSigmas: " << (Isis::IsSpecial(aprioriSigmas[0]) ? "N/A" : Isis::toString(aprioriSigmas[0])) << (Isis::IsSpecial(aprioriSigmas[1]) ? "N/A" : Isis::toString(aprioriSigmas[1])) @@ -701,33 +768,43 @@ int main(int argc, char *argv[]) { qDebug() << "weights: " << weights[0] << weights[1] << weights[2]; qDebug() << ""; - ControlPoint *cp = bcp1.rawControlPoint(); + ControlPoint *cp = bcp1b.rawControlPoint(); qDebug() << "Raw control point equal to original? " << toString(*cp == *freePoint); - qDebug() << "Raw control point is rejected? " << toString(bcp1.isRejected()); - SurfacePoint sp = bcp1.adjustedSurfacePoint(); + qDebug() << "Raw control point is rejected? " << toString(bcp1b.isRejected()); + SurfacePoint sp = bcp1b.adjustedSurfacePoint(); qDebug() << "Adjusted SurfacePoint (Lat, Lon, Rad) = " << toString(sp.GetLatitude().degrees()) << toString(sp.GetLongitude().degrees()) << toString(sp.GetLocalRadius().meters()); qDebug() << ""; - qDebug() << "Create FixedPoint from empty fixed point, adjusted surface point (90, 180, 10)..."; +// Testing of Free point settings is complete + +// Fixed point tests + qDebug() << "BCP test 5 - Create FixedPoint from empty fixed point, solveRadius = F" + " adjusted surface point (90, 180, 10)..."; ControlPoint *fixedPoint = new ControlPoint("FixedPoint"); fixedPoint->SetType(ControlPoint::Fixed); - BundleControlPoint *bcp3 = new BundleControlPoint(fixedPoint); + settings->setSolveOptions(false, false, false, false, SurfacePoint::Latitudinal, + SurfacePoint::Latitudinal, Isis::Null); + BundleControlPoint *bcp3a = new BundleControlPoint(settings, fixedPoint); SurfacePoint sp2(Latitude(90.0, Angle::Degrees), Longitude(180.0, Angle::Degrees), Distance(10.0, Distance::Meters)); - bcp3->setAdjustedSurfacePoint(sp2); - qDebug().noquote() << bcp3->formatBundleOutputSummaryString(errorProp); - qDebug().noquote() << bcp3->formatBundleOutputDetailString(errorProp, radiansToMeters); - - qDebug() << "Modify FixedPoint - setWeights()"; - bcp3->setWeights(settings, metersToRadians); - qDebug().noquote() << bcp3->formatBundleOutputSummaryString(errorProp); - qDebug().noquote() << bcp3->formatBundleOutputDetailString(errorProp, radiansToMeters); - aprioriSigmas = bcp3->aprioriSigmas(); - weights = bcp3->weights(); + bcp3a->setAdjustedSurfacePoint(sp2); + qDebug().noquote() << bcp3a->formatBundleOutputSummaryString(errorProp); + qDebug().noquote() << bcp3a->formatBundleOutputDetailString(errorProp); + + qDebug() << "BCP test 6 - Create FixedPoint from empty fixed point, solveRadius = True"; + qDebug() << " adjusted surface point (90, 180, 10)..."; +settings->setSolveOptions(false, false, false, true, SurfacePoint::Latitudinal, + SurfacePoint::Latitudinal, Isis::Null); + BundleControlPoint *bcp3b = new BundleControlPoint(settings, fixedPoint); + bcp3b->setAdjustedSurfacePoint(sp2); + qDebug().noquote() << bcp3b->formatBundleOutputSummaryString(errorProp); + qDebug().noquote() << bcp3b->formatBundleOutputDetailString(errorProp, true); + aprioriSigmas = bcp3b->aprioriSigmas(); + weights = bcp3b->weights(); qDebug() << "aprioriSigmas: " << (Isis::IsSpecial(aprioriSigmas[0]) ? "NULL" : Isis::toString(aprioriSigmas[0])) << (Isis::IsSpecial(aprioriSigmas[1]) ? "NULL" : Isis::toString(aprioriSigmas[1])) @@ -735,21 +812,20 @@ int main(int argc, char *argv[]) { qDebug() << "weights: " << weights[0] << weights[1] << weights[2]; qDebug() << ""; - qDebug() << "Create ConstrainedPoint from empty constrained point, surface point (0, 0, 10)..."; +// Testing of FixedPoint output completed + +// #7 ConstrainedPoint test with surface point with coordinates only. SolveRadius is false. + qDebug() << "BCP test 7 - Create ConstrainedPoint with solveRadius=false and adjusted " + "surface point (0, 0, 10), no constraints set, coordType=Latitudinal ..."; ControlPoint *constrainedPoint = new ControlPoint("ConstrainedPoint"); constrainedPoint->SetType(ControlPoint::Constrained); - BundleControlPoint bcp4(constrainedPoint); - bcp4.setAdjustedSurfacePoint(sp1); - qDebug().noquote() << bcp4.formatBundleOutputSummaryString(errorProp); - qDebug().noquote() << bcp4.formatBundleOutputDetailString(errorProp, radiansToMeters); - - qDebug() << "Modify ConstrainedPoint - setWeights() - solveRadius=false"; settings->setSolveOptions(false, false, false, false); - bcp4.setWeights(settings, metersToRadians); - qDebug().noquote() << bcp4.formatBundleOutputSummaryString(errorProp); - qDebug().noquote() << bcp4.formatBundleOutputDetailString(errorProp, radiansToMeters); - aprioriSigmas = bcp4.aprioriSigmas(); - weights = bcp4.weights(); + BundleControlPoint bcp4a(settings, constrainedPoint); + bcp4a.setAdjustedSurfacePoint(sp1); + qDebug().noquote() << bcp4a.formatBundleOutputSummaryString(errorProp); + qDebug().noquote() << bcp4a.formatBundleOutputDetailString(errorProp); + aprioriSigmas = bcp4a.aprioriSigmas(); + weights = bcp4a.weights(); qDebug() << "aprioriSigmas: " << (Isis::IsSpecial(aprioriSigmas[0]) ? "NULL" : Isis::toString(aprioriSigmas[0])) << (Isis::IsSpecial(aprioriSigmas[1]) ? "NULL" : Isis::toString(aprioriSigmas[1])) @@ -757,14 +833,17 @@ int main(int argc, char *argv[]) { qDebug() << "weights: " << weights[0] << weights[1] << weights[2]; qDebug() << ""; - qDebug() << "Modify ConstrainedPoint - setWeights() - no constraints, solveRadius=true, " - "apriori lat/lon/rad <= 0"; +// #8 ConstrainedPoint with no constraints, but solveRadius=true + qDebug() << "BCP test 8 - Create ConstrainedPoint - no constraints, solveRadius=true, " + "apriori lat/lon/rad <= 0, "; + qDebug() << " and adjustedsurface point (0, 0, 10)"; settings->setSolveOptions(false, false, false, true); - bcp4.setWeights(settings, metersToRadians); - qDebug().noquote() << bcp4.formatBundleOutputSummaryString(errorProp); - qDebug().noquote() << bcp4.formatBundleOutputDetailString(errorProp, radiansToMeters); - aprioriSigmas = bcp4.aprioriSigmas(); - weights = bcp4.weights(); + BundleControlPoint bcp4b(settings, constrainedPoint); + bcp4b.setAdjustedSurfacePoint(sp1); + qDebug().noquote() << bcp4b.formatBundleOutputSummaryString(errorProp); + qDebug().noquote() << bcp4b.formatBundleOutputDetailString(errorProp, true); + aprioriSigmas = bcp4b.aprioriSigmas(); + weights = bcp4b.weights(); qDebug() << "aprioriSigmas: " << (Isis::IsSpecial(aprioriSigmas[0]) ? "NULL" : Isis::toString(aprioriSigmas[0])) << (Isis::IsSpecial(aprioriSigmas[1]) ? "NULL" : Isis::toString(aprioriSigmas[1])) @@ -772,53 +851,82 @@ int main(int argc, char *argv[]) { qDebug() << "weights: " << weights[0] << weights[1] << weights[2]; qDebug() << ""; - qDebug() << "Modify ConstrainedPoint - setWeights() - no constraints, solveRadius=true, " - "apriori lat/lon/rad > 0"; - settings->setSolveOptions(false, false, false, true, 2.0, 3.0, 4.0); - bcp4.setWeights(settings, metersToRadians); - qDebug().noquote() << bcp4.formatBundleOutputSummaryString(errorProp); - qDebug().noquote() << bcp4.formatBundleOutputDetailString(errorProp, radiansToMeters); - aprioriSigmas = bcp4.aprioriSigmas(); - weights = bcp4.weights(); +// #9 ConstrainedPoint with no constraints set, solveRadius=true, and valid global sigmas. + qDebug() << "BCP test 9 - Create ConstrainedPoint - no constraints, solveRadius=true," + " apriori lat/lon/rad > 0 (valid global sigmas)"; + settings->setSolveOptions(false, false, false, true, SurfacePoint::Latitudinal, + SurfacePoint::Latitudinal, 2.0, 3.0, 4.0); + constrainedPoint->SetAprioriSurfacePoint(sp1); + BundleControlPoint bcp4c(settings, constrainedPoint); + bcp4c.setAdjustedSurfacePoint(sp1); + qDebug().noquote() << bcp4c.formatBundleOutputSummaryString(errorProp); + qDebug().noquote() << bcp4c.formatBundleOutputDetailString(errorProp); + aprioriSigmas = bcp4c.aprioriSigmas(); + weights = bcp4c.weights(); qDebug() << "aprioriSigmas: " << (Isis::IsSpecial(aprioriSigmas[0]) ? "NULL" : Isis::toString(aprioriSigmas[0])) << (Isis::IsSpecial(aprioriSigmas[1]) ? "NULL" : Isis::toString(aprioriSigmas[1])) << (Isis::IsSpecial(aprioriSigmas[2]) ? "NULL" : Isis::toString(aprioriSigmas[2])); - qDebug() << "weights: " << weights[0] << weights[1] << weights[2]; + if (!IsSpecial(weights[0]) && !IsSpecial(weights[1]) && !IsSpecial(weights[2])) { + qDebug() << "weights: " << weights[0] << weights[1] << weights[2]; + } + else { + qDebug() << "weights: NA"; + } + qDebug() << ""; qDebug() << ""; - qDebug() << "Create ConstrainedPoint from constrained point with adjusted surface point " - "(32, 120, 1000)..."; +// #10 ConstrainedPoint with apriori and adjusted surface points fully set and solveRadius=F. + qDebug() << "BCP test 10 - Create ConstrainedPoint from constrained point with adjusted "; + qDebug() << " pt (32, 120, 1000) & apriori pt with constraints from covar, solveRadius=F..."; SurfacePoint aprioriSurfPt; boost::numeric::ublas::symmetric_matrix covar; covar.resize(3); covar.clear(); - covar(0,0) = 100.0; - covar(1,1) = 2500.0; - covar(2,2) = 400.0; + covar(0,0) = 100.; + covar(1,1) = 2500.; + covar(2,2) = 400.; aprioriSurfPt.SetRectangular(Displacement(-424.024048, Displacement::Meters), Displacement(734.4311949, Displacement::Meters), Displacement(529.919264, Displacement::Meters), covar); +// Extract the covar matrix converted to latitudinal coordinates now to use for test 10. +// Usage note: In order to get accurate results, the full correlation matrix should be +// used as opposed to only setting the diagonal elements with the sigmas. + boost::numeric::ublas::symmetric_matrix covarLat(3); + covarLat.clear(); + covarLat = aprioriSurfPt.GetSphericalMatrix(); + +// These results match what is being set in adjusted surface point. + Angle latSigma = aprioriSurfPt.GetLatSigma(); + Angle lonSigma = aprioriSurfPt.GetLonSigma(); + Distance localRad = aprioriSurfPt.GetLocalRadiusSigma(); constrainedPoint->SetAprioriSurfacePoint(aprioriSurfPt); - BundleControlPoint bcp5(constrainedPoint); + settings->setSolveOptions(false, false, false, false); + BundleControlPoint bcp5a(settings, constrainedPoint); SurfacePoint adjustedSurfPt(constrainedPoint->GetAdjustedSurfacePoint()); - adjustedSurfPt.SetSpherical(Latitude(32., Angle::Degrees), + adjustedSurfPt.SetSphericalCoordinates(Latitude(32., Angle::Degrees), Longitude(120., Angle::Degrees), - Distance(1000., Distance::Meters), - Angle(1.64192315,Angle::Degrees), - Angle(1.78752107, Angle::Degrees), - Distance(38.454887335682053718134171237789, Distance::Meters)); - bcp5.setAdjustedSurfacePoint(adjustedSurfPt); - qDebug().noquote() << bcp5.formatBundleOutputSummaryString(errorProp); - qDebug().noquote() << bcp5.formatBundleOutputDetailString(errorProp, radiansToMeters); - qDebug() << "Modify ConstrainedPoint - setWeights() - solveRadius=t, lat/lon/rad constrained"; - bcp5.setWeights(settings, metersToRadians); - qDebug().noquote() << bcp5.formatBundleOutputSummaryString(errorProp); - qDebug().noquote() << bcp5.formatBundleOutputDetailString(errorProp, radiansToMeters); - aprioriSigmas = bcp5.aprioriSigmas(); // these values were verified by comparing against + Distance(1000., Distance::Meters)); + adjustedSurfPt.SetSphericalMatrix(covarLat); + // Angle(1.64192315,Angle::Degrees), + // Angle(1.78752107, Angle::Degrees), + // Distance(38.454887335682053718134171237789, Distance::Meters)); + bcp5a.setAdjustedSurfacePoint(adjustedSurfPt); + qDebug().noquote() << bcp5a.formatBundleOutputSummaryString(errorProp); + qDebug().noquote() << bcp5a.formatBundleOutputDetailString(errorProp); + +// #11 ConstrainedPoint with apriori and adjusted surface points fully set and solveRadius=T. + qDebug() << "BCP test 11 - Create ConstrainedPoint from constrained point with adjusted surface" + " pt (32, 120, 1000) "; + qDebug() << " & apriori pt with constraints from covar, solveRadius=T..."; + settings->setSolveOptions(false, false, false, true); + BundleControlPoint bcp5b(settings, constrainedPoint); + qDebug().noquote() << bcp5b.formatBundleOutputSummaryString(errorProp); + qDebug().noquote() << bcp5b.formatBundleOutputDetailString(errorProp); + aprioriSigmas = bcp5b.aprioriSigmas(); // these values were verified by comparing against // SurfacePoint truth data - weights = bcp5.weights(); + weights = bcp5b.weights(); qDebug() << "aprioriSigmas: " << (Isis::IsSpecial(aprioriSigmas[0]) ? "NULL" : Isis::toString(aprioriSigmas[0])) << (Isis::IsSpecial(aprioriSigmas[1]) ? "NULL" : Isis::toString(aprioriSigmas[1])) @@ -826,31 +934,138 @@ int main(int argc, char *argv[]) { qDebug() << "weights: " << weights[0] << weights[1] << weights[2]; qDebug() << ""; - qDebug() << "Create copy of FreePoint using copy constructor..."; - BundleControlPoint bcp2(bcp1); +// #12 FreePoint - test copy constructor by copying bcp1b + qDebug() << "BCP test 12 - Create copy of FreePoint using copy constructor..."; +// Should we use bundleSettings or settings here? + BundleControlPoint bcp2(bcp1b); qDebug().noquote() << bcp2.formatBundleOutputSummaryString(errorProp); //solveForRadius = false by default in formatBundleDetailString qDebug() << "Output for formatBundleOutputDetailString(...) with solveForRadius = false:"; - qDebug().noquote() << bcp2.formatBundleOutputDetailString(errorProp, radiansToMeters); + qDebug().noquote() << bcp2.formatBundleOutputDetailString(errorProp); //solveForRadius = true - qDebug() << "Output for formatBundleOutputDetailString(...) with solveForRadius = true:"; - qDebug().noquote() << bcp2.formatBundleOutputDetailString(errorProp, radiansToMeters,true); + qDebug() << "BCP test 13 - Output for formatBundleOutputDetailString(...) with " + "solveForRadius = true:"; + qDebug().noquote() << bcp2.formatBundleOutputDetailString(errorProp, true); qDebug() << ""; - qDebug() << "Overwrite existing object with FixedPoint information..."; - bcp2.copy(*bcp3); + qDebug() << "BCP test 14 - Overwrite existing object with FixedPoint information..."; + bcp2.copy(*bcp3b); qDebug().noquote() << bcp2.formatBundleOutputSummaryString(errorProp); - qDebug().noquote() << bcp2.formatBundleOutputDetailString(errorProp, radiansToMeters); + qDebug().noquote() << bcp2.formatBundleOutputDetailString(errorProp); + qDebug() << ""; + + qDebug() << "BCP test 15 - Coordtype=Rect, Free, solveRad=F"; + settings->setSolveOptions(false, false, false, false, SurfacePoint::Rectangular, + SurfacePoint::Rectangular); + BundleControlPoint bcp1c(settings, freePoint); + qDebug().noquote() << bcp1c.formatBundleOutputSummaryString(errorProp); + qDebug().noquote() << bcp1c.formatBundleOutputDetailString(errorProp); + weights = bcp1c.weights(); + qDebug() << "weights: " << weights[0] << weights[1] << weights[2]; + qDebug() << ""; + + qDebug() << "BCP test 16 - Coordtype=Rect, Free, solveRad=T"; + settings->setSolveOptions(false, false, false, true, SurfacePoint::Rectangular, + SurfacePoint::Rectangular, 2.0, 3.0, 4.0); + BundleControlPoint bcp1d(settings, freePoint); + qDebug().noquote() << bcp1d.formatBundleOutputSummaryString(errorProp); + qDebug().noquote() << bcp1d.formatBundleOutputDetailString(errorProp); + weights = bcp1d.weights(); + qDebug() << "weights: " << weights[0] << weights[1] << weights[2]; + qDebug() << ""; + qDebug() << ""; + + qDebug() << "BCP test 17 - Coordtype=Rect, Fixed, solveRad=F"; + settings->setSolveOptions(false, false, false, false, SurfacePoint::Rectangular, + SurfacePoint::Rectangular, 2.0, 3.0, 4.0); + sp2.SetRectangular(Displacement(0.0, Displacement::Meters), + Displacement(0.0, Displacement::Meters), + Displacement(1000.0, Displacement::Meters)); + BundleControlPoint *bcp3c = new BundleControlPoint(settings, fixedPoint); + bcp3c->setAdjustedSurfacePoint(sp2); + qDebug().noquote() << bcp3c->formatBundleOutputSummaryString(errorProp); + qDebug().noquote() << bcp3c->formatBundleOutputDetailString(errorProp); + weights = bcp3c->weights(); + qDebug() << "weights: " << weights[0] << weights[1] << weights[2]; + qDebug() << ""; qDebug() << ""; + +// #18 ConstrainedPoint test with surface point with coordinates only. SolveRadius is false. + qDebug() << "BCP test 18 - Create ConstrainedPoint with solveRadius=false and adjusted " + "surface point (0, 0, 1000), no constraints set, and coordType = Rect ..."; + SurfacePoint sp3(Displacement(0.0, Displacement::Meters), + Displacement(0.0, Displacement::Meters), + Displacement(1000.0, Displacement::Meters)); + ControlPoint *constrainedPointRect = new ControlPoint("ConstrainedPoint"); + constrainedPointRect->SetType(ControlPoint::Constrained); + settings->setSolveOptions(false, false, false, false, SurfacePoint::Rectangular, + SurfacePoint::Rectangular); + BundleControlPoint bcp4d(settings, constrainedPointRect); + bcp4d.setAdjustedSurfacePoint(sp3); + qDebug().noquote() << bcp4d.formatBundleOutputSummaryString(errorProp); + qDebug().noquote() << bcp4d.formatBundleOutputDetailString(errorProp); + aprioriSigmas = bcp4d.aprioriSigmas(); + weights = bcp4d.weights(); + qDebug() << "aprioriSigmas: " + << (Isis::IsSpecial(aprioriSigmas[0]) ? "NULL" : Isis::toString(aprioriSigmas[0])) + << (Isis::IsSpecial(aprioriSigmas[1]) ? "NULL" : Isis::toString(aprioriSigmas[1])) + << (Isis::IsSpecial(aprioriSigmas[2]) ? "NULL" : Isis::toString(aprioriSigmas[2])); + qDebug() << "weights: " << weights[0] << weights[1] << weights[2]; + qDebug() << ""; + +// #19 ConstrainedPoint test with surface point with coordinates only. SolveRadius is false. + qDebug() << "BCP test 19 - Create ConstrainedPoint with solveRadius=false and adjusted " + "surface point (0, 0, 1000), valid globals, and coordType = Rect ..."; + // SurfacePoint sp3(Displacement(0.0, Displacement::Meters), + // Displacement(0.0, Displacement::Meters), + // Displacement(1000.0, Displacement::Meters)); + // ControlPoint *constrainedPointRect = new ControlPoint("ConstrainedPoint"); + // constrainedPointRect->SetType(ControlPoint::Constrained); + settings->setSolveOptions(false, false, false, false, SurfacePoint::Rectangular, + SurfacePoint::Rectangular, 2.0, 3.0, 4.0); + BundleControlPoint bcp4e(settings, constrainedPointRect); + bcp4e.setAdjustedSurfacePoint(sp3); + qDebug().noquote() << bcp4e.formatBundleOutputSummaryString(errorProp); + qDebug().noquote() << bcp4e.formatBundleOutputDetailString(errorProp); + aprioriSigmas = bcp4e.aprioriSigmas(); + weights = bcp4e.weights(); + qDebug() << "aprioriSigmas: " + << (Isis::IsSpecial(aprioriSigmas[0]) ? "NULL" : Isis::toString(aprioriSigmas[0])) + << (Isis::IsSpecial(aprioriSigmas[1]) ? "NULL" : Isis::toString(aprioriSigmas[1])) + << (Isis::IsSpecial(aprioriSigmas[2]) ? "NULL" : Isis::toString(aprioriSigmas[2])); + qDebug() << "weights: " << weights[0] << weights[1] << weights[2]; + qDebug() << ""; + +// #20 ConstrainedPoint with apriori and adjusted surface points fully set and solveRadius=F. + qDebug() << "BCP test 20 - Create ConstrainedPoint from constrained point with adjusted "; + qDebug() << " pt (32, 120, 1000) & apriori pt from Test 10 with constraints from covar, solveRadius=F, "; + qDebug() << "coordType=Rectangular..."; + qDebug() << ""; +// This test uses an apriori surface point set with rectangular coordinates and sigmas. The adjusted +// surface point is set with latitudinal coordinates equivalent to the apriori surface point coordinates. +// The covar for the adjusted surface point is generated from the apriori covar converted to latitudinal +// coordinates. Using just the sigmas to set the diagonal elements of the covar is not accurate. + constrainedPointRect->SetAprioriSurfacePoint(aprioriSurfPt); +settings->setSolveOptions(false, false, false, false, SurfacePoint::Rectangular, SurfacePoint::Rectangular); + BundleControlPoint bcp5c(settings, constrainedPointRect); + bcp5c.setAdjustedSurfacePoint(adjustedSurfPt); + qDebug().noquote() << bcp5c.formatBundleOutputSummaryString(errorProp); + qDebug().noquote() << bcp5c.formatBundleOutputDetailString(errorProp); + +// #21 Test error condition - invalid BundleControlPoint coordinate type + qDebug() << "BCP test 21 - Test invalid coordinate type "; + qDebug() << ""; + settings->setSolveOptions(false, false, false, false, SurfacePoint::CoordinateType(3)); + qDebug() << "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"; qDebug() << ""; qDebug() << "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"; qDebug() << "Testing BundleMeasure..."; // TEST COVERAGE (SCOPE) FOR THIS SOURCE FILE: 86% //TODO update when SquishCoco works again - BundleMeasure bundleMeasure(cm2, bcp3); + BundleMeasure bundleMeasure(cm2, bcp3b); try { bundleMeasure.observationSolveSettings(); diff --git a/isis/src/control/objs/ControlNet/ControlNet.cpp b/isis/src/control/objs/ControlNet/ControlNet.cpp index 94162a307179e315893f627e6a0b750f5176bbc8..c4ab2d53a8286e3886565421a7e1306c58483d3f 100644 --- a/isis/src/control/objs/ControlNet/ControlNet.cpp +++ b/isis/src/control/objs/ControlNet/ControlNet.cpp @@ -48,9 +48,11 @@ namespace Isis { m_mutex = NULL; } + //!Creates an empty ControlNet object + ControlNet::ControlNet(SurfacePoint::CoordinateType coordType) { + //! Creates an empty ControlNet object - ControlNet::ControlNet() { - + // ControlNet::ControlNet() { nullify(); points = new QHash< QString, ControlPoint * >; @@ -59,6 +61,7 @@ namespace Isis { m_ownPoints = true; p_created = Application::DateTime(); p_modified = Application::DateTime(); + m_coordType = coordType; } ControlNet::ControlNet(const ControlNet &other) { @@ -83,6 +86,7 @@ namespace Isis { p_userName = other.p_userName; p_cameraMap = other.p_cameraMap; p_cameraList = other.p_cameraList; + m_coordType = other.m_coordType; } @@ -92,15 +96,17 @@ namespace Isis { * @param ptfile Name of network file * @param progress A pointer to the progress of reading in the control points */ - ControlNet::ControlNet(const QString &ptfile, Progress *progress) { - + ControlNet::ControlNet(const QString &ptfile, Progress *progress, + SurfacePoint::CoordinateType coordType) { + nullify(); points = new QHash< QString, ControlPoint * >; pointIds = new QStringList; m_ownPoints = true; - + m_coordType = coordType; + try { ReadControl(ptfile, progress); } @@ -839,6 +845,16 @@ namespace Isis { } + /** + * Sets the control point coordinate type + * + * @param coordType Control point coordinate type + */ + void ControlNet::SetCoordType(SurfacePoint::CoordinateType coordType) { + m_coordType = coordType; + } + + /** * This method is a wrapper to emit the networkStructureModified() signal. */ @@ -1830,6 +1846,15 @@ namespace Isis { } + /** + * Get the control point coordinate type (see the available types in SurfacePoint.h). + * + * @returns the control point coordinate type + */ + SurfacePoint::CoordinateType ControlNet::GetCoordType() { + return m_coordType; + } + const ControlPoint *ControlNet::operator[](QString id) const { return GetPoint(id); } diff --git a/isis/src/control/objs/ControlNet/ControlNet.h b/isis/src/control/objs/ControlNet/ControlNet.h index bbaeac682710b419b89cc742fdbaff3cde4ac8b3..ae1adb546386e46ab86f3ea4e733cb7084bc5dbf 100644 --- a/isis/src/control/objs/ControlNet/ControlNet.h +++ b/isis/src/control/objs/ControlNet/ControlNet.h @@ -27,6 +27,7 @@ #include #include // parent class #include +#include "SurfacePoint.h" #include #include #include @@ -213,6 +214,10 @@ namespace Isis { * @history 2017-08-09 Summer Stapleton - Added throw to caught exception for bad control net * import in constructor. Also removed p_invalid as it was no longer * being used anywhere. Fixes #5068. + * @history 2017-08-30 Debbie A. Cook - Added an optional argument to the constructor + * for the control point coordinate type. At this point this value is only + * stored in the active ControlNet. It will be added to the stored + * ControlNet at a later date. References #4649 and #501. * @history 2017-12-12 Kristin Berry - Updated to use QMap and QVector rather than std::map * and std::vector. Fixes #5259. * @history 2017-12-18 Adam Goins - Added GetLastModified() accessor. References #5258. @@ -285,9 +290,10 @@ namespace Isis { GraphModified }; - ControlNet(); + ControlNet(SurfacePoint::CoordinateType = SurfacePoint::Latitudinal); ControlNet(const ControlNet &other); - ControlNet(const QString &filename, Progress *progress = 0); + ControlNet(const QString &filename, Progress *progress = 0, + SurfacePoint::CoordinateType = SurfacePoint::Latitudinal); ~ControlNet(); @@ -347,7 +353,7 @@ namespace Isis { QString GetLastModified() const; QList< ControlPoint * > GetPoints(); QList< QString > GetPointIds() const; - + SurfacePoint::CoordinateType GetCoordType(); void SetCreatedDate(const QString &date); void SetDescription(const QString &newDescription); @@ -361,6 +367,7 @@ namespace Isis { void SetTarget(Pvl label); void SetTarget(const ControlNet &other); void SetUserName(const QString &name); + void SetCoordType(SurfacePoint::CoordinateType coordType); void swap(ControlNet &other); ControlNet &operator=(const ControlNet &other); @@ -481,7 +488,8 @@ namespace Isis { //! #rejected measures QVector p_cameraList; //!< Vector of image number to camera - bool m_ownPoints; //!< Specifies ownership of point list. True if owned by this object. + bool m_ownPoints; //!< Specifies ownership of point list. True if owned by this object. + SurfacePoint::CoordinateType m_coordType; //!< The coordinate type of the control points }; //! This typedef is for future implementation of target body diff --git a/isis/src/control/objs/ControlNetVersioner/ControlNetVersioner.cpp b/isis/src/control/objs/ControlNetVersioner/ControlNetVersioner.cpp index a7885e5884c742196f52c38aa30aef86ac5061cd..60f8bf47bff5d8aad77ed8694aee52237ab3e8ba 100644 --- a/isis/src/control/objs/ControlNetVersioner/ControlNetVersioner.cpp +++ b/isis/src/control/objs/ControlNetVersioner/ControlNetVersioner.cpp @@ -319,6 +319,7 @@ namespace Isis { if ( aprioriCovarianceMatrix.size1() > 0 ) { + // Matrix units are meters squared PvlKeyword matrix("AprioriCovarianceMatrix"); matrix += toString(aprioriCovarianceMatrix(0, 0)); matrix += toString(aprioriCovarianceMatrix(0, 1)); @@ -327,6 +328,8 @@ namespace Isis { matrix += toString(aprioriCovarianceMatrix(1, 2)); matrix += toString(aprioriCovarianceMatrix(2, 2)); + // *** TODO *** What do we do in the case of bundled in rectangular coordinates? + // For now we do nothing. if ( aprioriSurfacePoint.GetLatSigmaDistance().meters() != Isis::Null && aprioriSurfacePoint.GetLonSigmaDistance().meters() != Isis::Null && aprioriSurfacePoint.GetLocalRadiusSigma().meters() != Isis::Null ) { @@ -354,15 +357,17 @@ namespace Isis { } } - if ( controlPoint->IsLatitudeConstrained() ) { + // Deal with the generalization here. *** TODO *** + // Once we have a coordinate type in the header, we should specify the correct coordinate + if ( controlPoint->IsCoord1Constrained() ) { pvlPoint += PvlKeyword("LatitudeConstrained", "True"); } - if ( controlPoint->IsLongitudeConstrained() ) { + if ( controlPoint->IsCoord2Constrained() ) { pvlPoint += PvlKeyword("LongitudeConstrained", "True"); } - if ( controlPoint->IsRadiusConstrained() ) { + if ( controlPoint->IsCoord2Constrained() ) { pvlPoint += PvlKeyword("RadiusConstrained", "True"); } @@ -1913,14 +1918,15 @@ namespace Isis { } } // this might be redundant... determined by covariance matrix??? - if ( controlPoint->IsLatitudeConstrained() ) { - protoPoint.set_latitudeconstrained(controlPoint->IsLatitudeConstrained()); + // *** TODO *** Address the generalized coordinates and the constraint differences + if ( controlPoint->IsCoord1Constrained() ) { + protoPoint.set_latitudeconstrained(controlPoint->IsCoord1Constrained()); } - if ( controlPoint->IsLongitudeConstrained() ) { - protoPoint.set_longitudeconstrained(controlPoint->IsLongitudeConstrained()); + if ( controlPoint->IsCoord2Constrained() ) { + protoPoint.set_longitudeconstrained(controlPoint->IsCoord2Constrained()); } - if ( controlPoint->IsRadiusConstrained() ) { - protoPoint.set_radiusconstrained(controlPoint->IsRadiusConstrained()); + if ( controlPoint->IsCoord3Constrained() ) { + protoPoint.set_radiusconstrained(controlPoint->IsCoord3Constrained()); } SurfacePoint adjustedSurfacePoint = controlPoint->GetAdjustedSurfacePoint(); diff --git a/isis/src/control/objs/ControlNetVersioner/ControlNetVersioner.h b/isis/src/control/objs/ControlNetVersioner/ControlNetVersioner.h index 2270b47a971426dfd9e9f3a2a860ff75c932f12d..4623cfff02c423923bb436c441a20781e409cdf7 100644 --- a/isis/src/control/objs/ControlNetVersioner/ControlNetVersioner.h +++ b/isis/src/control/objs/ControlNetVersioner/ControlNetVersioner.h @@ -399,16 +399,28 @@ namespace Isis { * Target::GetRadii calls to speed up createPoint(). * @history 2018-01-12 Adam Goins - Added Progress during reads. * @history 2018-01-24 Jesse Mapel - Fixed c++11 build warnings. + * * @history 2018-01-27 Jesse Mapel - Fixed some documentation formatting. Added a section * describing the different file format versions. * @history 2018-01-30 Adam Goins - Ensured point sizes are written/read as lsb by using * EndianSwapper. + * @history 2018-02-25 Debbie A. Cook - Generalized calls to + * ControlPoint::IsLatitudeConstrained to IsCoord1Constained + * and added or updated a few comments. *** TODO *** make sure + * the new methods are fully functional for either coordinate type + * once the new header keyword is added. * @history 2018-03-28 Adam Goins - Added targetRadii groups to the header. Changed the * versioner to write these values out in a targetRadii group for * both binary V0005 and PvlV0005 networks. Fixes #5361. * @history 2018-04-05 Adam Goins - Added hasTargetRadii() and targetRadii() to the versioner * so that these values can be grabbed from a ControlNet on read. * Also Fixes #5361. + * @history 2018-06-01 Debbie A. Cook - (added to BundleXYZ 2018-02-25) + * Generalized calls to ControlPoint::IsLatitudeConstrained to + * IsCoord1Constained and added or updated a few comments. + * *** TODO *** make sure the new methods are fully functional + * for either coordinate type once the new header keyword is added. + * * @history 2018-07-03 Jesse Mapel - Removed target radii from versioner. References #5457. */ class ControlNetVersioner { diff --git a/isis/src/control/objs/ControlPoint/ControlPoint.cpp b/isis/src/control/objs/ControlPoint/ControlPoint.cpp index 11174ed2aa40a47cdc9b18459f5ea80bbec64528..80fa615662ba34894c2deba7bb6725a026ac6cfd 100644 --- a/isis/src/control/objs/ControlPoint/ControlPoint.cpp +++ b/isis/src/control/objs/ControlPoint/ControlPoint.cpp @@ -108,7 +108,6 @@ namespace Isis { } - /** * Construct a control point with given Id * @@ -192,7 +191,7 @@ namespace Isis { * It was also decided that when importing old * networks that contain Sigmas, the sigmas will not * be imported , due to conflicts with the units of - * the sigmas,we cannot get accurate x,y,z sigams from + * the sigmas,we cannot get accurate x,y,z sigmas from * the lat,lon,radius sigmas without the covariance * matrix. * @history 2010-09-28 Tracie Sucharski, Added back the conversion methods @@ -684,6 +683,7 @@ namespace Isis { */ ControlPoint::Status ControlPoint::SetAdjustedSurfacePoint( SurfacePoint newSurfacePoint) { + PointModified(); adjustedSurfacePoint = newSurfacePoint; return Success; @@ -770,18 +770,33 @@ namespace Isis { */ ControlPoint::Status ControlPoint::SetAprioriSurfacePoint( SurfacePoint aprioriSP) { + SurfacePoint::CoordinateType coordType = SurfacePoint::Latitudinal; + if (parentNetwork) { + coordType = parentNetwork->GetCoordType(); + } if (editLock) { return PointLocked; } - if (aprioriSP.GetLatSigma().isValid()) { - constraintStatus.set(LatitudeConstrained); - } - if (aprioriSP.GetLonSigma().isValid()) { - constraintStatus.set(LongitudeConstrained); - } - if (aprioriSP.GetLocalRadiusSigma().isValid()) { - constraintStatus.set(RadiusConstrained); - } + // ***TBD*** Does it make sense to try to do a generic check here? The + // data types are different (angles vs distance) so for now do a switch. + switch (coordType) { + case SurfacePoint::Latitudinal: + if (aprioriSP.GetLatSigma().isValid()) + constraintStatus.set(Coord1Constrained); + if (aprioriSP.GetLonSigma().isValid()) + constraintStatus.set(Coord2Constrained); + if (aprioriSP.GetLocalRadiusSigma().isValid()) + constraintStatus.set(Coord3Constrained); + break; + case SurfacePoint::Rectangular: + if (aprioriSP.GetXSigma().isValid()) + constraintStatus.set(Coord1Constrained); + if (aprioriSP.GetYSigma().isValid()) + constraintStatus.set(Coord2Constrained); + if (aprioriSP.GetZSigma().isValid()) + constraintStatus.set(Coord3Constrained); + } + PointModified(); aprioriSurfacePoint = aprioriSP; return Success; @@ -854,6 +869,9 @@ namespace Isis { * points, which are already left unchanged by * ComputeApriori. If a free point is editLocked * the editLock will be ignored by this method. + * @history 2017-04-25 Debbie A. Cook - change constraint status calls + * to use generic coordinate names (Coord1, Coord2, + * and Coord3). * * @return Status Success or PointLocked */ @@ -863,7 +881,7 @@ namespace Isis { // Don't goof with fixed points. The lat/lon is what it is ... if // it exists! // 2013-11-12 KLE I think this check should include points with any - // number of constrained coordinates??? + // number of constrained coordinates??? I agree DAC. *** TODO *** if (GetType() == Fixed) { if (!aprioriSurfacePoint.Valid()) { QString msg = "ControlPoint [" + GetId() + "] is a fixed point "; @@ -942,9 +960,9 @@ namespace Isis { // constrained coordinates > 1" ??? else if (GetType() == Fixed || NumberOfConstrainedCoordinates() == 3 - || IsLatitudeConstrained() - || IsLongitudeConstrained() - || IsRadiusConstrained()) { + || IsCoord1Constrained() + || IsCoord2Constrained() + || IsCoord3Constrained()) { // Initialize the adjusted x/y/z to the a priori coordinates adjustedSurfacePoint = aprioriSurfacePoint; @@ -952,6 +970,7 @@ namespace Isis { return Success; } + // Beyond this point, we assume the point is free ***TODO*** confirm this // Did we have any measures? if (goodMeasures == 0) { QString msg = "ControlPoint [" + GetId() + "] has no measures which " @@ -959,7 +978,7 @@ namespace Isis { throw IException(IException::User, msg, _FILEINFO_); } - // Compute the averages + // Compute the averages if all coordinates are free //if (NumberOfConstrainedCoordinates() == 0) { if (GetType() == Free || NumberOfConstrainedCoordinates() == 0) { double avgX = xB / goodMeasures; @@ -973,14 +992,6 @@ namespace Isis { Displacement((avgY*scale), Displacement::Kilometers), Displacement((avgZ*scale), Displacement::Kilometers)); } - // Since we are not solving yet for x,y,and z in the bundle directly, - // longitude must be constrained. This constrains x and y as well. - else { - aprioriSurfacePoint.SetRectangular( - aprioriSurfacePoint.GetX(), - aprioriSurfacePoint.GetY(), - Displacement((zB / goodMeasures), Displacement::Kilometers)); - } adjustedSurfacePoint = aprioriSurfacePoint; SetAprioriSurfacePointSource(SurfacePointSource::AverageOfMeasures); @@ -1039,7 +1050,7 @@ namespace Isis { double cuLine; CameraFocalPlaneMap *fpmap = m->Camera()->FocalPlaneMap(); - // Map the lat/lon/radius of the control point through the Spice of the + // Map the coordinates of the control point through the Spice of the // measurement sample/line to get the computed sample/line. This must be // done manually because the camera will compute a new time for line scanners, // instead of using the measured time. @@ -1194,7 +1205,7 @@ namespace Isis { Camera *cam = m->Camera(); double cudx, cudy; - // Map the lat/lon/radius of the control point through the Spice of the + // Map the coordinates of the control point through the Spice of the // measurement sample/line to get the computed undistorted focal plane // coordinates (mm if not radar). This works for radar too because in // the undistorted focal plane, y has not been set to 0 (set to 0 when @@ -1574,16 +1585,16 @@ namespace Isis { return constraintStatus.any(); } - bool ControlPoint::IsLatitudeConstrained() { - return constraintStatus[LatitudeConstrained]; + bool ControlPoint::IsCoord1Constrained() { + return constraintStatus[Coord1Constrained]; } - bool ControlPoint::IsLongitudeConstrained() { - return constraintStatus[LongitudeConstrained]; + bool ControlPoint::IsCoord2Constrained() { + return constraintStatus[Coord2Constrained]; } - bool ControlPoint::IsRadiusConstrained() { - return constraintStatus[RadiusConstrained]; + bool ControlPoint::IsCoord3Constrained() { + return constraintStatus[Coord3Constrained]; } int ControlPoint::NumberOfConstrainedCoordinates() { @@ -2109,6 +2120,7 @@ namespace Isis { /** * Set jigsaw rejected flag for all measures to false * and set the jigsaw rejected flag for the point itself to false + * */ void ControlPoint::ClearJigsawRejected() { int nmeasures = measures->size(); diff --git a/isis/src/control/objs/ControlPoint/ControlPoint.h b/isis/src/control/objs/ControlPoint/ControlPoint.h index 6ee45f0cbbe07bea338f60b1dfc719807a52dfe7..89fe54ff292e00620f773a8eb66b9251c814adb6 100644 --- a/isis/src/control/objs/ControlPoint/ControlPoint.h +++ b/isis/src/control/objs/ControlPoint/ControlPoint.h @@ -335,6 +335,9 @@ namespace Isis { * @history 2015-11-05 Kris Becker - invalid flag was not properly * initialized in ControlPointFileEntryV0002 * constructor (Merged by Kristin Berry. Fixes #2392) + * @history 2017-05-25 Debbie A. Cook - coordType to SetPrioriSurfacePoint with a default of + * Latitudinal. Changed LatitudeConstrained to Coord1Constrained, etc. + * References #4649 and #501. * @history 2017-12-18 Kristin Berry - Added convenience methods: * HasAprioriSurfacePointSourceFile(), HasAprioriRadiusSourceFile(), * HasRefMeasure(). @@ -419,18 +422,9 @@ namespace Isis { * coordinates in the SurfacePoint */ enum ConstraintStatus { - /** - * This is the status of constrained coordinates in the SurfacePoint. - * @todo We will eventually need to deal with rectangular - * coordinates as well, but for now BundleAdjust uses spherical - * coordinates only. - */ - LatitudeConstrained = 0, - LongitudeConstrained = 1, - RadiusConstrained = 2, -// XConstrained = 3, -// YConstrained = 4, -// ZConstrained = 5; + Coord1Constrained = 0, + Coord2Constrained = 1, + Coord3Constrained = 2 }; /** @@ -533,14 +527,15 @@ namespace Isis { QString GetId() const; bool IsIgnored() const; bool IsValid() const; + // Can we get rid of this? It doesn't appear to be used anywhere. *** ToDo *** bool IsInvalid() const; bool IsFixed() const; bool HasAprioriCoordinates(); bool IsConstrained(); - bool IsLatitudeConstrained(); - bool IsLongitudeConstrained(); - bool IsRadiusConstrained(); + bool IsCoord1Constrained(); + bool IsCoord2Constrained(); + bool IsCoord3Constrained(); int NumberOfConstrainedCoordinates(); static QString PointTypeToString(PointType type); @@ -671,7 +666,7 @@ namespace Isis { /** * This stores the constraint status of the a priori SurfacePoint - * @todo Eventually add x, y, and z + * @todo Eventually add x, y, and z. Instead we made generic coordinates */ std::bitset<6> constraintStatus; diff --git a/isis/src/control/objs/ControlPoint/unitTest.cpp b/isis/src/control/objs/ControlPoint/unitTest.cpp index 9a108b0a10f6fd94323ad9a0e9b41d78e3ef1acc..6ad1b08a340231c5d0a07e431a2b6dd3644317ed 100644 --- a/isis/src/control/objs/ControlPoint/unitTest.cpp +++ b/isis/src/control/objs/ControlPoint/unitTest.cpp @@ -15,7 +15,7 @@ using namespace std; using namespace boost::numeric::ublas; using namespace Isis; -void printPoint(ControlPoint &p); +void printPoint(ControlPoint &p, bool = false); /** * @brief Test ControlPoint object for accuracy and correct behavior. @@ -34,7 +34,7 @@ void printPoint(ControlPoint &p); * @history 2017-12-21 Kristin Berry - Added tests for newly added accessor methods. * @history 2018-01-04 Adam Goins - Replaced QDebug with std::cout. Removed commented out code for * Removed accessor methods. - */ + */ int main() { Preference::Preferences(true); @@ -266,7 +266,7 @@ int main() { } } -void printPoint(Isis::ControlPoint &p) { +void printPoint(Isis::ControlPoint &p, bool testRect) { bool wasLocked = p.IsEditLocked(); p.SetEditLock(false); p.SetChooserName("cnetref"); @@ -314,4 +314,19 @@ void printPoint(Isis::ControlPoint &p) { cout << "Printing point:\n" << tmp << "\nDone printing point." << std::endl; std::cout << std::endl; remove("./tmp.net"); + + // Add test with coordinate type set to Rectangular *** TBD *** Add test once + // changes are made to the protocol buffer. + if (testRect) { + ControlNet recNet; + recNet.AddPoint(copyPoint); + recNet.SetNetworkId("Identifier"); + recNet.SetCreatedDate("Yesterday"); + recNet.SetModifiedDate("Yesterday"); + recNet.Write("./tmpR.net", true); + Pvl tmpR("./tmpR.net"); + cout << "Printing rectangular net point:\n" << tmp << "\nDone printing point." + << endl << endl; + remove("./tmpR.net"); + } } diff --git a/isis/src/qisis/apps/qtie/QtieTool.cpp b/isis/src/qisis/apps/qtie/QtieTool.cpp index 41b7f5a947f02a3c2fd3cefd9f82338dd8c3c1fe..28f05c487615d2881dd09a84e967cd67654db858 100644 --- a/isis/src/qisis/apps/qtie/QtieTool.cpp +++ b/isis/src/qisis/apps/qtie/QtieTool.cpp @@ -795,7 +795,8 @@ namespace Isis { // longitude sigma = 1000.0 // radius sigma = Null since we are not solving for radius // outlier rejection = false - settings->setSolveOptions(false, false, false, false, 1000.0, 1000.0, Isis::Null); + settings->setSolveOptions(false, false, false, false, SurfacePoint::Latitudinal, + SurfacePoint::Latitudinal, 1000.0,1000.0, Isis::Null); //************************************************************************************************ QList observationSolveSettingsList; BundleObservationSolveSettings observationSolveSettings; diff --git a/isis/src/qisis/objs/ConcurrentControlNetReader/ConcurrentControlNetReader.h b/isis/src/qisis/objs/ConcurrentControlNetReader/ConcurrentControlNetReader.h index c6ce80919a5965f79010a62d03aa58354144b160..74d6574bd3c42aac47aaf2095f9499324302392f 100644 --- a/isis/src/qisis/objs/ConcurrentControlNetReader/ConcurrentControlNetReader.h +++ b/isis/src/qisis/objs/ConcurrentControlNetReader/ConcurrentControlNetReader.h @@ -52,7 +52,7 @@ namespace Isis { * * @internal * @history 2017-08-09 Summer Stapleton - Added a try-catch block to handle invalid control - * networks. Fixes #5068. + * networks. Fixes #5068. */ class ConcurrentControlNetReader : public QObject { Q_OBJECT diff --git a/isis/src/qisis/objs/JigsawRunWidget/JigsawRunWidget.cpp b/isis/src/qisis/objs/JigsawRunWidget/JigsawRunWidget.cpp index d967579f24316f4d5ab02a149486bf55204d3d17..1a65dcc084391765ecf3ea25e981ffa3bfa5e5be 100644 --- a/isis/src/qisis/objs/JigsawRunWidget/JigsawRunWidget.cpp +++ b/isis/src/qisis/objs/JigsawRunWidget/JigsawRunWidget.cpp @@ -602,13 +602,13 @@ namespace Isis { if (m_bundleSettings->errorPropagation()) { m_ui->rmsAdjustedPointSigmasGroupBox->setEnabled(true); m_ui->latitudeLcdNumber->display( - m_bundleSolutionInfo->bundleResults().sigmaLatitudeStatisticsRms()); + m_bundleSolutionInfo->bundleResults().sigmaCoord1StatisticsRms()); m_ui->longitudeLcdNumber->display( - m_bundleSolutionInfo->bundleResults().sigmaLongitudeStatisticsRms()); + m_bundleSolutionInfo->bundleResults().sigmaCoord2StatisticsRms()); if (m_bundleSettings->solveRadius()) { m_ui->radiusLcdNumber->display( - m_bundleSolutionInfo->bundleResults().sigmaRadiusStatisticsRms()); + m_bundleSolutionInfo->bundleResults().sigmaCoord3StatisticsRms()); m_ui->radiusLcdNumber->setEnabled(true); m_ui->radiusLcdLabel->setEnabled(true); } diff --git a/isis/src/qisis/objs/JigsawSetupDialog/JigsawSetupDialog.cpp b/isis/src/qisis/objs/JigsawSetupDialog/JigsawSetupDialog.cpp index 5df8a1e3a56d917bb9d65a7520fc5a1e832e98c1..ced53c15e24878afdb80954cd3102a8c1659e40a 100644 --- a/isis/src/qisis/objs/JigsawSetupDialog/JigsawSetupDialog.cpp +++ b/isis/src/qisis/objs/JigsawSetupDialog/JigsawSetupDialog.cpp @@ -471,16 +471,16 @@ namespace Isis { m_ui->maximumIterationsLineEdit->setText(toString(settings->convergenceCriteriaMaximumIterations())); // weighting tab - if ( !IsNullPixel(settings->globalLatitudeAprioriSigma()) ) { - m_ui->pointLatitudeSigmaLineEdit->setText(toString(settings->globalLatitudeAprioriSigma())); + if ( !IsNullPixel(settings->globalPointCoord1AprioriSigma()) ) { + m_ui->pointLatitudeSigmaLineEdit->setText(toString(settings->globalPointCoord1AprioriSigma())); m_ui->pointLatitudeSigmaLineEdit->setModified(true); } - if ( !IsNullPixel(settings->globalLongitudeAprioriSigma()) ) { - m_ui->pointLongitudeSigmaLineEdit->setText(toString(settings->globalLongitudeAprioriSigma())); + if ( !IsNullPixel(settings->globalPointCoord2AprioriSigma()) ) { + m_ui->pointLongitudeSigmaLineEdit->setText(toString(settings->globalPointCoord2AprioriSigma())); m_ui->pointLongitudeSigmaLineEdit->setModified(true); } - if ( !IsNullPixel(settings->globalRadiusAprioriSigma()) ) { - m_ui->pointRadiusSigmaLineEdit->setText(toString(settings->globalRadiusAprioriSigma())); + if ( !IsNullPixel(settings->globalPointCoord3AprioriSigma()) ) { + m_ui->pointRadiusSigmaLineEdit->setText(toString(settings->globalPointCoord3AprioriSigma())); m_ui->pointRadiusSigmaLineEdit->setModified(true); } @@ -529,11 +529,14 @@ namespace Isis { if (m_ui->pointRadiusSigmaLineEdit->isModified()) { radiusSigma = m_ui->pointRadiusSigmaLineEdit->text().toDouble(); } + // Stick with the default coordinate types for the bundle and reports until + // a gui is added to get the settings settings->setSolveOptions(m_ui->observationModeCheckBox->isChecked(), false, // m_ui->updateCubeLabelCheckBox->isChecked(), m_ui->errorPropagationCheckBox->isChecked(), m_ui->pointRadiusSigmaCheckBox->isChecked(), + SurfacePoint::Latitudinal, SurfacePoint::Latitudinal, latitudeSigma, longitudeSigma, radiusSigma); diff --git a/isis/src/qisis/objs/QnetTools/QnetSetAprioriDialog.cpp b/isis/src/qisis/objs/QnetTools/QnetSetAprioriDialog.cpp index 08aaf9dff82d62874ff59cd8cf6291577ea36eb2..2f9f7102da8bab4d28d5478f8ae0759971776ab3 100644 --- a/isis/src/qisis/objs/QnetTools/QnetSetAprioriDialog.cpp +++ b/isis/src/qisis/objs/QnetTools/QnetSetAprioriDialog.cpp @@ -543,11 +543,10 @@ namespace Isis { // longitude must be constrained. This constrains x and y as well. else if (!(pt->GetPointTypeString() == "Fixed") && !(pt->NumberOfConstrainedCoordinates() == 3) && - !pt->IsLatitudeConstrained() && - !pt->IsLongitudeConstrained() && - !pt->IsRadiusConstrained()){ - - aprioriSurfacePoint.SetRectangular( + !pt->IsCoord1Constrained() && + !pt->IsCoord2Constrained() && + !pt->IsCoord3Constrained()){ + aprioriSurfacePoint.SetRectangular( Displacement(aprioriSurfacePoint.GetX().meters(), Displacement::Meters), Displacement(aprioriSurfacePoint.GetY().meters(), Displacement::Meters), Displacement((zB / goodMeasures), Displacement::Kilometers)); diff --git a/isis/src/qisis/objs/TableMainWindow/TableMainWindow.cpp b/isis/src/qisis/objs/TableMainWindow/TableMainWindow.cpp index 12e6b3a02f75b272340eec0d33d5cb420af9f16c..e0f6295258868d96348613a3ac4ffc4466814910 100644 --- a/isis/src/qisis/objs/TableMainWindow/TableMainWindow.cpp +++ b/isis/src/qisis/objs/TableMainWindow/TableMainWindow.cpp @@ -223,7 +223,6 @@ namespace Isis { destinationColumn = startCol + i; p_table->insertColumn(startCol + i); } - QTableWidgetItem *header = new QTableWidgetItem(htext); if (insertAt >= 0) { @@ -371,6 +370,10 @@ namespace Isis { /** * This method checks to see if the table has been created. If * not it calls the createTable method before calling show. + * + * @history 2017-10-06 Adam Goins - showTable() now calls syncColumns() after it calls + * this->show() so that it hides the unselected columns appropriately. + * Fixes #5141. * * @history 2017-10-06 Adam Goins - showTable() now calls syncColumns() after it calls * this->show() so that it hides the unselected columns appropriately. diff --git a/isis/src/qisis/objs/WindowTool/WindowTool.cpp b/isis/src/qisis/objs/WindowTool/WindowTool.cpp index 351737eeefc74014afae0d44af40a4d121e50030..bbe797d1c8d4c025d5c4797c5faabc40060bdf4c 100644 --- a/isis/src/qisis/objs/WindowTool/WindowTool.cpp +++ b/isis/src/qisis/objs/WindowTool/WindowTool.cpp @@ -166,8 +166,7 @@ namespace Isis { return std::max(sx,sy); } - - /** + /** * Tiles the cube viewports over the Cube DN View. * * @internal