Isis 3 Programmer Reference
BundleControlPoint.cpp
1
7/* SPDX-License-Identifier: CC0-1.0 */
8
9#include "BundleControlPoint.h"
10
11#include <QDebug>
12
13// boost lib
14#include <boost/numeric/ublas/vector_proxy.hpp>
15
16// Isis lib
17#include "ControlMeasure.h"
18#include "Latitude.h"
19#include "LinearAlgebra.h"
20#include "Longitude.h"
21#include "SparseBlockMatrix.h"
22#include "SpecialPixel.h"
23
24namespace Isis {
25
26
34 ControlPoint *controlPoint) {
35 m_controlPoint = controlPoint;
36
37 // setup vector of BundleMeasures for this control point
38 int numMeasures = controlPoint->GetNumMeasures();
39 for (int i = 0; i < numMeasures; i++) {
40 ControlMeasure *controlMeasure = controlPoint->GetMeasure(i);
41 if (controlMeasure->IsIgnored()) {
42 continue;
43 }
44
45 addMeasure(controlMeasure);
46 }
47
48 // initialize to 0.0
49 m_corrections.clear();
50 m_weights.clear();
51 m_nicVector.clear();
52
53 // initialize to Null for consistency with other bundle classes...
54 m_aprioriSigmas.clear();
58 m_adjustedSigmas.clear();
62
63 // initialize coordinate type from settings
64 // m_coordType = SurfacePoint::Latitudinal;
65 m_coordTypeReports = bundleSettings->controlPointCoordTypeReports();
66 m_coordTypeBundle = bundleSettings->controlPointCoordTypeBundle();
67 setWeights(bundleSettings);
68 }
69
70
80
81
87
88
95
96 // sanity check
97 clear();
98
99 m_controlPoint = src.m_controlPoint;
100
101 int numMeasures = src.size();
102
103 for (int i = 0; i < numMeasures; i++)
104 append(BundleMeasureQsp( new BundleMeasure(*(src.at(i))) ));
105
106 m_corrections = src.m_corrections;
107 m_aprioriSigmas = src.m_aprioriSigmas;
108 m_adjustedSigmas = src.m_adjustedSigmas;
109 m_weights = src.m_weights;
110 m_nicVector = src.m_nicVector;
111 m_coordTypeReports = src.m_coordTypeReports;
112 m_coordTypeBundle = src.m_coordTypeBundle;
113 // *** TODO *** Why is the cholmodQMatrix not copied? Ask Ken
114 }
115
116
126
127 BundleMeasureQsp bundleMeasure = BundleMeasureQsp( new BundleMeasure(controlMeasure, this) );
128
129 append(bundleMeasure);
130
131 return bundleMeasure;
132 }
133
134
142
143 // compute and store focal plane residuals in millimeters
144 for (int i = 0; i < size(); i++) {
145 at(i)->setFocalPlaneResidualsMillimeters();
146 }
147 }
148
149
158
159
170
171
181 }
182
183
192
193 double globalPointCoord1AprioriSigma = settings->globalPointCoord1AprioriSigma();
194 double globalPointCoord2AprioriSigma = settings->globalPointCoord2AprioriSigma();
195 double globalPointCoord3AprioriSigma = settings->globalPointCoord3AprioriSigma();
196
198 m_weights[0] = 1.0e+50;
199 m_weights[1] = 1.0e+50;
200 m_weights[2] = 1.0e+50;
201 // m_aprioriSigmas = Isis::Null by default
202 }
203
205 // Global sigmas are temporary and should not be stored in the control net. Currently
206 // global sigmas are always in meters. Make sure unit of weights is 1/(var unit squared),
207 // where var is a value being solved for in the adjustment. Latitude and longitude are in
208 // radians and everything else is in km.
209 if (!IsSpecial(globalPointCoord1AprioriSigma)) {
210 setSigmaWeightFromGlobals(globalPointCoord1AprioriSigma, 0);
211 } // else m_aprioriSigma = Isis::Null
212 // m_weights = 0.0
213 if (!IsSpecial(globalPointCoord2AprioriSigma)) {
214 m_aprioriSigmas[1] = globalPointCoord2AprioriSigma;
215 setSigmaWeightFromGlobals(globalPointCoord2AprioriSigma, 1);
216 }// else m_aprioriSigma = Isis::Null
217 // m_weights = 0.0
218 if (m_coordTypeBundle == SurfacePoint::Latitudinal && !settings->solveRadius()) {
219 m_weights[2] = 1.0e+50;
220 }
221 else {
222 if (!IsSpecial(globalPointCoord3AprioriSigma)) {
223 setSigmaWeightFromGlobals(globalPointCoord3AprioriSigma, 2);
224 }
225 }
226 }
228 // *** Be careful...Is m_aprioriSigmas an output (for reports) or bundle variable? ***
229
230 // Assuming the member variable sigmas are for output reports (internal use only) so use
231 // the report coordinate type to calculate. All point sigmas are in meters. Radius weights
232 // are in 1/km^2. Make x/y/z weights the same because BundleAdjust works in km.
233 // Weights and corrections go into the bundle so use bundle coordinate type.
235 m_aprioriSigmas[0] =
236 m_controlPoint->GetAprioriSurfacePoint().GetSigmaDistance
237 (m_coordTypeReports, SurfacePoint::One).meters();
238 m_weights[0] =
239 m_controlPoint->GetAprioriSurfacePoint().GetWeight(m_coordTypeBundle, SurfacePoint::One);
240 }
241 else if (!IsSpecial(globalPointCoord1AprioriSigma)) {
242 setSigmaWeightFromGlobals(globalPointCoord1AprioriSigma, 0);
243 } // else not constrained and global sigma is Null, then m_aprioriSigmas = Isis::Null
244 // m_weights = 0.0
245
247 m_aprioriSigmas[1] =
248 m_controlPoint->GetAprioriSurfacePoint().GetSigmaDistance
249 (m_coordTypeReports, SurfacePoint::Two).meters();
250 m_weights[1] =
251 m_controlPoint->GetAprioriSurfacePoint().GetWeight(m_coordTypeBundle, SurfacePoint::Two);
252 }
253 else if (!IsSpecial(globalPointCoord2AprioriSigma)) {
254 setSigmaWeightFromGlobals(globalPointCoord2AprioriSigma, 1);
255 } // else not constrained and global sigma is Null, then m_aprioriSigmas = Isis::Null
256 // m_weights = 0.0
257
258 if (m_coordTypeBundle == SurfacePoint::Latitudinal && !settings->solveRadius()) {
259 m_weights[2] = 1.0e+50;
260 }
261 else {
263 m_aprioriSigmas[2] =
264 m_controlPoint->GetAprioriSurfacePoint().GetSigmaDistance
265 (m_coordTypeReports, SurfacePoint::Three).meters();
266 m_weights[2] = m_controlPoint->GetAprioriSurfacePoint().GetWeight
267 (m_coordTypeBundle, SurfacePoint::Three);
268 }
269 else if (!IsSpecial(globalPointCoord3AprioriSigma)) {
270 setSigmaWeightFromGlobals(globalPointCoord3AprioriSigma, 2);
271 } // else not constrained and global sigma is Null, then m_aprioriSigmas = Isis::Null
272 // m_weights = 0.0
273 }
274 }
275 }
276
277
288 void BundleControlPoint::setSigmaWeightFromGlobals(double gSigma, int index) {
289 m_aprioriSigmas[index] = gSigma;
290
291 switch (index) {
292 case 0:
293 if (m_coordTypeBundle == SurfacePoint::Latitudinal) {
294 m_aprioriSigmas[index] = gSigma;
295 double sigmaRadians =
296 m_controlPoint->GetAprioriSurfacePoint().MetersToLatitude(gSigma); // m to radians
297 if (sigmaRadians > DBL_EPSILON) {
298 m_weights[index] = 1. / (sigmaRadians*sigmaRadians); // 1/radians^2
299 }
300 }
301 else if (m_coordTypeBundle == SurfacePoint::Rectangular) {
302 double sigmakm = gSigma * .001; // km
303 if (sigmakm > DBL_EPSILON) {
304 m_weights[0] = 1./ (sigmakm*sigmakm); // 1/km^2
305 }
306 }
307 else {
308 IString msg ="Unknown surface point coordinate type enum ["
309 + toString(m_coordTypeBundle) + "]." ;
310 throw IException(IException::Programmer, msg, _FILEINFO_);
311 }
312 break;
313 case 1:
314 // if (!IsSpecial(globalPointCoord2AprioriSigma)) {
315 if (m_coordTypeBundle == SurfacePoint::Latitudinal) {
316 double sigmaRadians =
317 m_controlPoint->GetAprioriSurfacePoint().MetersToLongitude(gSigma); // m to radians
318 if (sigmaRadians > DBL_EPSILON) {
319 m_weights[1] = 1. / (sigmaRadians*sigmaRadians); // 1/radians^2
320 }
321 }
322 else if (m_coordTypeBundle == SurfacePoint::Rectangular) {
323 double sigmakm = gSigma * 0.001; // km
324 if (sigmakm > DBL_EPSILON) m_weights[1] = 1./ (sigmakm*sigmakm); // 1/km^2
325 }
326 else {
327 IString msg ="Unknown surface point coordinate type enum ["
328 + toString(m_coordTypeBundle) + "]." ;
329 throw IException(IException::Programmer, msg, _FILEINFO_);
330 }
331 break;
332
333 case 2:
334 // Coordinate 2 is either latitudinal radius or rectangular z, both in m
335 {
336 double sigmakm = gSigma * .001; // km
337 m_weights[2] = 1./ (sigmakm*sigmakm); // 1/km^2
338 }
339 break;
340
341 default:
342 IString msg ="Unknown coordinate index [" + toString(index) + "]." ;
343 throw IException(IException::Programmer, msg, _FILEINFO_);
344 }
345 }
346
347
356
357
368 SparseBlockMatrix &sparseNormals,
370
371 QMapIterator< int, LinearAlgebra::Matrix * > Qit(m_cholmodQMatrix);
372
373 int subrangeStart, subrangeEnd;
374
375 while ( Qit.hasNext() ) {
376 Qit.next();
377
378 int columnIndex = Qit.key();
379
380 subrangeStart = sparseNormals.at(columnIndex)->startColumn();
381 subrangeEnd = subrangeStart + Qit.value()->size2();
382
383 m_nicVector += alpha * prod(*(Qit.value()),subrange(v1,subrangeStart,subrangeEnd));
384 }
385 }
386
387
396 SparseBlockMatrix &sparseNormals,
397 const BundleTargetBodyQsp target) {
398 if (!isRejected()) {
399
400 // subtract product of Q and nj from NIC
401 productAlphaAV(-1.0, sparseNormals, imageSolution);
402
403 // update adjusted surface point appropriately for the coordinate type
404 switch (m_coordTypeBundle) {
407 break;
410 break;
411 default:
412 IString msg ="Unknown surface point coordinate type enum ["
413 + toString(m_coordTypeBundle) + "]." ;
414 throw IException(IException::Programmer, msg, _FILEINFO_);
415 }
416
417 // sum and save corrections
418 m_corrections(0) += m_nicVector[0];
419 m_corrections(1) += m_nicVector[1];
420 m_corrections(2) += m_nicVector[2];
421 }
422 }
423
424
433
434
441 return m_controlPoint->IsRejected();
442 }
443
444
451 return this->size();
452 }
453
454
465
466
476 }
477
478
485 return m_controlPoint->GetAdjustedSurfacePoint();
486 }
487
488
494 QString BundleControlPoint::id() const {
495 return m_controlPoint->GetId();
496 }
497
498
510
511
523
524
534 return m_coordTypeBundle;
535 }
536
537
538// *** TODO *** Need to add bounded vectors to Linear Algebra class
546 boost::numeric::ublas::bounded_vector< double, 3 > &BundleControlPoint::corrections() {
547 return m_corrections;
548 }
549
550
557 boost::numeric::ublas::bounded_vector< double, 3 > &BundleControlPoint::aprioriSigmas() {
558 return m_aprioriSigmas;
559 // Be careful about units. Latitude and longitude sigmas are in radians. Radius and X/Y/Z are
560 // meters.
561
562 }
563
564
571 boost::numeric::ublas::bounded_vector< double, 3 > &BundleControlPoint::adjustedSigmas() {
572 return m_adjustedSigmas;
573 }
574
575
582 boost::numeric::ublas::bounded_vector< double, 3 > &BundleControlPoint::weights() {
583 return m_weights;
584 }
585
586
592 boost::numeric::ublas::bounded_vector<double, 3> &BundleControlPoint::nicVector() {
593 return m_nicVector;
594 }
595
596
605
606
621 QString BundleControlPoint::formatBundleOutputSummaryString(bool errorPropagation) const {
622
623 int numRays = numberOfMeasures(); // should this depend on the raw point, as written, or this->size()???
624 int numGoodRays = numRays - numberOfRejectedMeasures();
625 double ResidualRms = residualRms();
626
627 // Return generic set of control point coordinates as floating point values
628 // Be careful because of the potential to confuse units.
629 SurfacePoint::CoordUnits units = SurfacePoint::Degrees;
630 if (m_coordTypeReports == SurfacePoint::Rectangular) units = SurfacePoint::Kilometers;
631 double cpc1 = m_controlPoint->GetAdjustedSurfacePoint().GetCoord(m_coordTypeReports,
632 SurfacePoint::One, units);
633 double cpc2 = m_controlPoint->GetAdjustedSurfacePoint().GetCoord(m_coordTypeReports,
634 SurfacePoint::Two, units);
635 double cpc3 = m_controlPoint->GetAdjustedSurfacePoint().GetCoord(m_coordTypeReports,
636 SurfacePoint::Three, SurfacePoint::Kilometers);
637
638 QString pointType = ControlPoint::PointTypeToString(type()).toUpper();
639
640 QString output = QString("%1%2%3 of %4%5%6%7%8%9%10%11\n")
641 .arg(id(), 16)
642 .arg(pointType, 15)
643 .arg(numGoodRays, 5)
644 .arg(numRays)
645 .arg(formatValue(ResidualRms, 6, 2))
646 .arg(formatValue(cpc1, 16, 8)) // deg km
647 .arg(formatValue(cpc2, 16, 8)) // deg OR km
648 .arg(formatValue(cpc3, 16, 8)) // km km
649 .arg(formatCoordAdjustedSigmaString(SurfacePoint::One, 16, 8, errorPropagation)) // m
650 .arg(formatCoordAdjustedSigmaString(SurfacePoint::Two, 16, 8, errorPropagation)) // m
651 .arg(formatCoordAdjustedSigmaString(SurfacePoint::Three, 16, 8, errorPropagation)); // m
652
653 return output;
654 }
655
656
669 bool solveRadius) const {
670 QString output;
671
672 switch (m_coordTypeReports) {
674 output = formatBundleLatitudinalOutputDetailString(errorPropagation, solveRadius);
675 break;
677 output = formatBundleRectangularOutputDetailString(errorPropagation);
678 break;
679 default:
680 IString msg ="Unknown surface point coordinate type enum [" + toString(m_coordTypeBundle) + "]." ;
681 throw IException(IException::Programmer, msg, _FILEINFO_);
682 }
683 return output;
684 }
685
686
708 bool errorPropagation,
709 bool solveRadius) const {
710
711 int numRays = numberOfMeasures();
712 int numGoodRays = numRays - numberOfRejectedMeasures();
713 double lat = m_controlPoint->GetAdjustedSurfacePoint().GetLatitude().degrees();
714 double lon = m_controlPoint->GetAdjustedSurfacePoint().GetLongitude().degrees();
715 double rad = m_controlPoint->GetAdjustedSurfacePoint().GetLocalRadius().kilometers();
716
717 // Use the local radius in meters, rad*1000., to convert radians to meters now instead of the
718 // target body equatorial radius DAC 09/17/2018
719 double rtm = rad * 1000.;
720
721 // Coordinate corrections are currently set in BundleAdjust::applyParameterCorrections in the
722 // coordTypeBundle coordinates (radians for Latitudinal coordinates and km for Rectangular).
723 // point corrections and initial sigmas
724 double cor_lat_dd = 0.; // lat correction, decimal degs
725 double cor_lon_dd = 0.; // lon correction, decimal degs
726 double cor_rad_km = 0.; // radius correction, kilometers
727 double cor_lat_m = 0.; // lat correction, meters
728 double cor_lon_m = 0.; // lon correction, meters
729 double cor_rad_m = 0.; // radius correction, meters
730 double latInit = Isis::Null;
731 double lonInit = Isis::Null;
732 double radInit = Isis::Null;
733
734 if (m_coordTypeBundle == SurfacePoint::Rectangular) {
735 double x = m_controlPoint->GetAdjustedSurfacePoint().GetX().kilometers();
736 double xCor = m_corrections(0); // km
737 double y = m_controlPoint->GetAdjustedSurfacePoint().GetY().kilometers();
738 double yCor = m_corrections(1); // km
739 double z = m_controlPoint->GetAdjustedSurfacePoint().GetZ().kilometers();
740 double zCor = m_corrections(2); // km
741
742 if (!IsSpecial(x) && !IsSpecial(y) && !IsSpecial(z)) {
746 latInit = rectPoint.GetLatitude().degrees();
747 lonInit = rectPoint.GetLongitude().degrees();
748 radInit = rectPoint.GetLocalRadius().kilometers();
749 if (!IsSpecial(lat)) {
750 cor_lat_dd = (lat - latInit); // degrees
751 cor_lat_m = cor_lat_dd * DEG2RAD * rtm;
752 }
753 if (!IsSpecial(lon)) {
754 cor_lon_dd = (lon - lonInit); // degrees
755 cor_lon_m = cor_lon_dd * DEG2RAD * rtm * cos(lat*DEG2RAD); // lon corrections meters
756 }
757 if (!IsSpecial(rad)) {
758 cor_rad_km = rad - radInit;
759 cor_rad_m = cor_rad_km * 1000.;
760 }
761 }
762 }
763 else if (m_coordTypeBundle == SurfacePoint::Latitudinal) {
764 cor_lat_dd = m_corrections(0) * RAD2DEG; // lat correction, decimal degs
765 cor_lon_dd = m_corrections(1) * RAD2DEG; // lon correction, decimal degs
766 cor_rad_m = m_corrections(2) * 1000.0; // radius correction, meters
767
768 cor_lat_m = m_controlPoint->GetAdjustedSurfacePoint().LatitudeToMeters(m_corrections(0));
769 cor_lon_m = m_controlPoint->GetAdjustedSurfacePoint().LongitudeToMeters(m_corrections(1));
770 cor_rad_km = m_corrections(2);
771
772 if (!IsSpecial(lat)) {
773 latInit = lat - cor_lat_dd;
774 }
775
776 if (!IsSpecial(lon)) {
777 lonInit = lon - cor_lon_dd;
778 }
779
780 if (!IsSpecial(rad)) {
781 radInit = rad - m_corrections(2); // km
782 }
783 }
784 else {
785 IString msg ="Unknown surface point coordinate type enum [" +
786 toString(m_coordTypeBundle) + "]." ;
787 throw IException(IException::Programmer, msg, _FILEINFO_);
788 }
789
790 QString pointType = ControlPoint::PointTypeToString(type()).toUpper();
791
792 QString output;
793
794 output = QString(" Label: %1\nStatus: %2\n Rays: %3 of %4\n")
795 .arg(id())
796 .arg(pointType)
797 .arg(numGoodRays)
798 .arg(numRays);
799
800 QString labels = "\n Point Initial Total Total "
801 " Final Initial Final\n"
802 "Coordinate Value Correction Correction "
803 " Value Accuracy Accuracy\n"
804 " (dd/dd/km) (dd/dd/km) (Meters) "
805 " (dd/dd/km) (Meters) (Meters)\n";
806 output += labels;
807
808 SurfacePoint::CoordIndex idx = SurfacePoint::One;
809 output += QString(" LATITUDE%1%2%3%4%5%6\n")
810 .arg(formatValue(latInit, 17, 8)) // deg
811 .arg(formatValue(cor_lat_dd, 21, 8)) // deg
812 .arg(formatValue(cor_lat_m, 20, 8)) // m
813 .arg(formatValue(lat, 20, 8)) // deg
814 .arg(formatCoordAprioriSigmaString(idx, 18,8, true)) // m
815 .arg(formatCoordAdjustedSigmaString(idx, 18,8,errorPropagation)); // m
816
817 idx = SurfacePoint::Two;
818 output += QString(" LONGITUDE%1%2%3%4%5%6\n")
819 .arg(formatValue(lonInit, 17, 8)) // deg
820 .arg(formatValue(cor_lon_dd, 21, 8)) // deg
821 .arg(formatValue(cor_lon_m, 20, 8)) // m
822 .arg(formatValue(lon, 20, 8)) // deg
823 .arg(formatCoordAprioriSigmaString(idx, 18,8, true)) // m
824 .arg(formatCoordAdjustedSigmaString(idx, 18,8,errorPropagation)); // m
825
826 idx = SurfacePoint::Three;
827 output += QString(" RADIUS%1%2%3%4%5%6\n\n")
828 .arg(formatValue(radInit, 17, 8)) // km
829 .arg(formatValue(cor_rad_km, 21, 8)) // km
830 .arg(formatValue(cor_rad_m, 20, 8)) // m
831 .arg(formatValue(rad, 20, 8)) // km
832 .arg(formatCoordAprioriSigmaString(idx, 18,8, solveRadius)) // m
833 .arg(formatCoordAdjustedSigmaString(idx, 18,8, errorPropagation)); // m
834
835 return output;
836 }
837
838
851 (bool errorPropagation) const {
852 int numRays = numberOfMeasures();
853 int numGoodRays = numRays - numberOfRejectedMeasures();
854 double X = m_controlPoint->GetAdjustedSurfacePoint().GetX().kilometers();
855 double Y = m_controlPoint->GetAdjustedSurfacePoint().GetY().kilometers();
856 double Z = m_controlPoint->GetAdjustedSurfacePoint().GetZ().kilometers();
857
858 // Coordinate corrections are currently set in applyParameterCorrections. Units depend on
859 // coordTypeBundle coordinates (radians for Latitudinal coordinates and km for Rectangular).
860 // point corrections and initial sigmas.....
861 double cor_X_m = 0.; // X correction, meters
862 double cor_Y_m = 0.; // Y correction, meters
863 double cor_Z_m = 0.; // Z correction, meters
864 double XInit = Isis::Null;
865 double YInit = Isis::Null;
866 double ZInit = Isis::Null;
867
868 if (m_coordTypeBundle == SurfacePoint::Latitudinal) {
869 double lat = m_controlPoint->GetAdjustedSurfacePoint().GetLatitude().degrees();
870 double latcor = m_corrections(0) * RAD2DEG;
871 double lon = m_controlPoint->GetAdjustedSurfacePoint().GetLongitude().degrees();
872 double loncor = m_corrections(1) * RAD2DEG;
873 double rad = m_controlPoint->GetAdjustedSurfacePoint().GetLocalRadius().kilometers();
874 double radcor = m_corrections(2);
875
876 if (!IsSpecial(lat) && !IsSpecial(lon) && !IsSpecial(rad)) {
877 SurfacePoint latPoint(Latitude(lat-latcor, Angle::Degrees),
878 Longitude(lon-loncor, Angle::Degrees),
879 Distance(rad-radcor, Distance::Kilometers));
880 XInit = latPoint.GetX().kilometers();
881 YInit = latPoint.GetY().kilometers();
882 ZInit = latPoint.GetZ().kilometers();
883 cor_X_m = Isis::Null;
884 if (!IsSpecial(X)) {
885 cor_X_m = (X - XInit); // kilometers
886 }
887 cor_Y_m = Isis::Null;
888 if (!IsSpecial(Y)) {
889 cor_Y_m = (Y - YInit); // kilometers
890 }
891 cor_Z_m = Isis::Null;
892 if (!IsSpecial(Z)) {
893 cor_Z_m = (Z - ZInit); // kilometers
894 }
895 }
896 }
897 else if (m_coordTypeBundle == SurfacePoint::Rectangular) {
898 cor_X_m = m_corrections(0); // X correction, kilometers
899 cor_Y_m = m_corrections(1); // Y correction, kilometers
900 cor_Z_m = m_corrections(2); // Z correction, kilometers
901 if (!IsSpecial(X)) {
902 XInit = X - m_corrections(0); // km
903 }
904 if (!IsSpecial(Y)) {
905 YInit = Y - m_corrections(1); // km
906 }
907 if (!IsSpecial(Z)) {
908 ZInit = Z - m_corrections(2); // km
909 }
910 }
911 else {
912 IString msg ="Unknown surface point coordinate type enum [" +
913 toString(m_coordTypeBundle) + "]." ;
914 throw IException(IException::Programmer, msg, _FILEINFO_);
915 }
916
917 QString pointType = ControlPoint::PointTypeToString(type()).toUpper();
918
919 QString output;
920
921 output = QString(" Label: %1\nStatus: %2\n Rays: %3 of %4\n")
922 .arg(id())
923 .arg(pointType)
924 .arg(numGoodRays)
925 .arg(numRays);
926
927 QString labels =
928 "\n Point Initial Total Final "
929 " Initial Final\n"
930 " Coordinate Value Correction Value "
931 " Accuracy Accuracy\n"
932 " (km/km/km) (km) (km/km/km) "
933 " (Meters) (Meters)\n";
934 output += labels;
935
936 SurfacePoint::CoordIndex idx = SurfacePoint::One;
937 output += QString(" BODY-FIXED-X%1%2%3%4%5\n")
938 .arg(formatValue(XInit, 17, 8)) // km
939 .arg(formatValue(cor_X_m, 20, 8)) // km
940 .arg(formatValue(X, 20, 8)) // km
941 .arg(formatCoordAprioriSigmaString(idx, 18,8, true)) // m
942 .arg(formatCoordAdjustedSigmaString(idx, 18,8,errorPropagation)); // m
943
944 idx = SurfacePoint::Two;
945 output += QString(" BODY-FIXED-Y%1%2%3%4%5\n")
946 .arg(formatValue(YInit, 17, 8)) // km
947 .arg(formatValue(cor_Y_m, 20, 8)) // km
948 .arg(formatValue(Y, 20, 8)) // km
949 .arg(formatCoordAprioriSigmaString(idx, 18, 8, true)) // m
950 .arg(formatCoordAdjustedSigmaString(idx, 18,8,errorPropagation)); // m
951
952 idx = SurfacePoint::Three;
953 output += QString(" BODY-FIXED-Z%1%2%3%4%5\n\n")
954 .arg(formatValue(ZInit, 17, 8)) // km
955 .arg(formatValue(cor_Z_m, 20, 8)) // km
956 .arg(formatValue(Z, 20, 8)) // km
957 // Set solveRadius to true to avoid limiting output information for Z.
958 // Set radius does not really apply to rectangular coordinates.
959 .arg(formatCoordAprioriSigmaString(idx, 18,8, true)) // m
960 .arg(formatCoordAdjustedSigmaString(idx, 18,8,errorPropagation)); // m
961
962 return output;
963 }
964
965
976 QString BundleControlPoint::formatValue(double value, int fieldWidth, int precision) const {
977 QString output;
978 IsSpecial(value) ?
979 output = QString("%1").arg("Null", fieldWidth) :
980 output = QString("%1").arg(value, fieldWidth, 'f', precision);
981 return output;
982 }
983
984
998 QString BundleControlPoint::formatAprioriSigmaString(SurfacePoint::CoordIndex index,
999 int fieldWidth, int precision,
1000 bool solveRadius) const {
1001 QString aprioriSigmaStr;
1002 QString pointType = ControlPoint::PointTypeToString(type()).toUpper();
1003 if (pointType == "CONSTRAINED" || !solveRadius) {
1004 pointType = "N/A";
1005 }
1006 double sigma = m_aprioriSigmas[int(index)];
1007 if (IsSpecial(sigma)) { // if globalAprioriSigma <= 0 (including Isis::Null), then m_aprioriSigmas = Null
1008 aprioriSigmaStr = QString("%1").arg(pointType, fieldWidth);
1009 }
1010 else {
1011 aprioriSigmaStr = QString("%1").arg(sigma, fieldWidth, 'f', precision);
1012 }
1013 return aprioriSigmaStr;
1014 }
1015
1016
1027QString BundleControlPoint::formatCoordAprioriSigmaString(SurfacePoint::CoordIndex index,
1028 int fieldWidth,
1029 int precision,
1030 bool solveRadius) const {
1031 return formatAprioriSigmaString(index, fieldWidth, precision, solveRadius);
1032 }
1033
1034
1048 QString BundleControlPoint::formatAdjustedSigmaString(SurfacePoint::CoordIndex index,
1049 int fieldWidth, int precision,
1050 bool errorPropagation) const {
1051 QString adjustedSigmaStr;
1052
1053 if (!errorPropagation) {
1054 adjustedSigmaStr = QString("%1").arg("N/A",fieldWidth);
1055 }
1056 else {
1057 double sigma = Isis::Null;
1059
1060 if (IsSpecial(sigma)) {
1061 adjustedSigmaStr = QString("%1").arg("N/A",fieldWidth);
1062 }
1063 else {
1064 adjustedSigmaStr = QString("%1").arg(sigma, fieldWidth, 'f', precision);
1065 }
1066 }
1067
1068 return adjustedSigmaStr;
1069 }
1070
1071
1084QString BundleControlPoint::formatCoordAdjustedSigmaString(SurfacePoint::CoordIndex index,
1085 int fieldWidth, int precision,
1086 bool errorPropagation) const {
1087 return formatAdjustedSigmaString(index, fieldWidth, precision, errorPropagation);
1088 }
1089
1090
1098 (const BundleTargetBodyQsp target) {
1099 SurfacePoint surfacepoint = adjustedSurfacePoint();
1100 double pointLat = surfacepoint.GetLatitude().degrees();
1101 double pointLon = surfacepoint.GetLongitude().degrees();
1102 double pointRad = surfacepoint.GetLocalRadius().meters();
1103
1104 // get point parameter corrections
1105 double latCorrection = m_nicVector[0];
1106 double lonCorrection = m_nicVector[1];
1107 double radCorrection = m_nicVector[2];
1108
1109 // convert to degrees and apply
1110 pointLat += RAD2DEG * latCorrection;
1111 pointLon += RAD2DEG * lonCorrection;
1112
1113 // Make sure updated values are still in valid range(0 to 360 for lon and -90 to 90 for lat)
1114 if (pointLat < -90.0) {
1115 pointLat = -180.0 - pointLat;
1116 pointLon = pointLon + 180.0;
1117 }
1118 if (pointLat > 90.0) {
1119 pointLat = 180.0 - pointLat;
1120 pointLon = pointLon + 180.0;
1121 }
1122 while (pointLon > 360.0) {
1123 pointLon = pointLon - 360.0;
1124 }
1125 while (pointLon < 0.0) {
1126 pointLon = pointLon + 360.0;
1127 }
1128
1129 // convert to meters and apply
1130 pointRad += 1000. * radCorrection;
1131
1132 // ken testing - if solving for target body mean radius, set radius to current
1133 // mean radius value
1134 // Only allow radius options for Latitudinal coordinates
1135 if (target && (target->solveMeanRadius() || target->solveTriaxialRadii()) ) {
1136 if (target->solveMeanRadius()) {
1137 surfacepoint.SetSphericalCoordinates(Latitude(pointLat, Angle::Degrees),
1138 Longitude(pointLon, Angle::Degrees),
1139 target->meanRadius());
1140 }
1141 else if (target->solveTriaxialRadii()) {
1142 Distance localRadius = target->localRadius(Latitude(pointLat, Angle::Degrees),
1143 Longitude(pointLon, Angle::Degrees));
1144 surfacepoint.SetSphericalCoordinates(Latitude(pointLat, Angle::Degrees),
1145 Longitude(pointLon, Angle::Degrees),
1146 localRadius);
1147 }
1148 }
1149 else {
1150 surfacepoint.SetSphericalCoordinates(Latitude(pointLat, Angle::Degrees),
1151 Longitude(pointLon, Angle::Degrees),
1152 Distance(pointRad, Distance::Meters));
1153 }
1154 // Reset the point now that it has been updated
1155 setAdjustedSurfacePoint(surfacepoint);
1156 }
1157
1158
1165 SurfacePoint surfacepoint = adjustedSurfacePoint();
1166 double pointX = surfacepoint.GetX().meters();
1167 double pointY = surfacepoint.GetY().meters();
1168 double pointZ = surfacepoint.GetZ().meters();
1169
1170 // get point parameter corrections
1171 double XCorrection = m_nicVector[0];
1172 double YCorrection = m_nicVector[1];
1173 double ZCorrection = m_nicVector[2];
1174
1175 // Convert corrections to meters and apply
1176 pointX += 1000. * XCorrection;
1177 pointY += 1000. * YCorrection;
1178 pointZ += 1000. * ZCorrection;
1179
1180 surfacepoint.SetRectangularCoordinates(Displacement(pointX, Displacement::Meters),
1183 // Reset the point now that it has been updated
1184 setAdjustedSurfacePoint(surfacepoint);
1185 }
1186
1187
1194
1195 double vtpv = 0.0;
1196 double weight = 0.0;
1197 double vx,vy;
1198
1199 for (int i = 0; i < size(); i++) {
1200 BundleMeasureQsp measure = at(i);
1201 if (measure->isRejected()) {
1202 continue;
1203 }
1204
1205 weight = measure->weight();
1206 vx = measure->xFocalPlaneResidual();
1207 vy = measure->yFocalPlaneResidual();
1208
1209 vtpv += vx * vx * weight + vy * vy * weight;
1210 }
1211
1212 return vtpv;
1213 }
1214
1215
1222 double vtpv = 0.0;
1223
1224 if ( m_weights(0) > 0.0 ) {
1225 vtpv += m_corrections(0) * m_corrections(0) * m_weights(0);
1226 }
1227 if ( m_weights(1) > 0.0 ) {
1228 vtpv += m_corrections(1) * m_corrections(1) * m_weights(1);
1229 }
1230 if ( m_weights(2) > 0.0 ) {
1231 vtpv += m_corrections(2) * m_corrections(2) * m_weights(2);
1232 }
1233
1234 return vtpv;
1235 }
1236}
double degrees() const
Get the angle in units of Degrees.
Definition Angle.h:232
@ Degrees
Degrees are generally considered more human readable, 0-360 is one circle, however most math does not...
Definition Angle.h:56
This class holds information about a control point that BundleAdjust needs to run correctly.
QString formatValue(double value, int fieldWidth, int precision) const
Formats the given double precision value using the specified field width and precision.
double residualRms() const
Gets the root-mean-square (rms) of the BundleControlPoint's residuals.
void setNumberOfRejectedMeasures(int numRejected)
Sets the number of rejected measures for this BundleControlPoint.
SparseBlockRowMatrix & cholmodQMatrix()
Accesses the CholMod matrix associated with this BundleControlPoint.
virtual void applyParameterCorrections(LinearAlgebra::Vector imageSolution, SparseBlockMatrix &sparseNormals, const BundleTargetBodyQsp target)
Apply the parameter corrections to the bundle control point.
QString formatBundleOutputDetailString(bool errorPropagation, bool solveRadius=false) const
Formats a detailed output string table for this BundleControlPoint.
SurfacePoint::CoordinateType coordTypeReports() const
Accesses BundleControlPoint's coordinate type for reports.
void setRejected(bool reject)
Sets this BundleControlPoint to rejected or not rejected.
boost::numeric::ublas::bounded_vector< double, 3 > m_nicVector
array of NICs (see Brown, 1976)
QString formatBundleRectangularOutputDetailString(bool errorPropagation) const
Formats a detailed output string table for this Rectangular BundleControlPoint.
void updateAdjustedSurfacePointRectangularly()
Apply the parameter corrections to the bundle control point rectangularly.
virtual ~BundleControlPoint()
Destructor for BundleControlPoint.
BundleControlPoint(BundleSettingsQsp bundleSettings, ControlPoint *point)
Constructs a BundleControlPoint object from a ControlPoint.
void productAlphaAV(double alpha, SparseBlockMatrix &sparseNormals, LinearAlgebra::Vector &v1)
Perform the matrix multiplication v2 = alpha ( Q x v1 ).
int numberOfRejectedMeasures() const
Accesses the number of rejected measures for this BundleControlPoint.
QString formatBundleLatitudinalOutputDetailString(bool errorPropagation, bool solveRadius=false) const
Formats a detailed output string table for this Latitudinal BundleControlPoint.
void updateAdjustedSurfacePointLatitudinally(const BundleTargetBodyQsp target)
Apply the parameter corrections to the bundle control point latitudinally.
double vtpvMeasures()
Compute vtpv of image measures (weighted sum of squares of measure residuals).
QString formatAprioriSigmaString(SurfacePoint::CoordIndex index, int fieldWidth, int precision, bool solveRadius=false) const
Formats the apriori sigma value indicated by the given type code.
boost::numeric::ublas::bounded_vector< double, 3 > m_corrections
corrections to point parameters
void zeroNumberOfRejectedMeasures()
Resets the number of rejected measures for this BundleControlPoint to zero.
void computeResiduals()
Computes the residuals for this BundleControlPoint.
SurfacePoint adjustedSurfacePoint() const
Accesses the adjusted SurfacePoint associated with this BundleControlPoint.
QString formatCoordAdjustedSigmaString(SurfacePoint::CoordIndex, int fieldWidth, int precision, bool errorPropagation) const
Formats the adjusted coordinate sigma value.
SurfacePoint::CoordinateType coordTypeBundle() const
Accesses BundleControlPoint's control point coordinate type for the bundle adjustment.
boost::numeric::ublas::bounded_vector< double, 3 > & nicVector()
Accesses the 3 dimensional ordered NIC vector.
double vtpv()
Compute vtpv, the weighted sum of squares of constrained point residuals.
ControlPoint::PointType type() const
Accesses BundleControlPoint's type.
boost::numeric::ublas::bounded_vector< double, 3 > & weights()
Accesses the 3 dimensional ordered vector of weight values associated with coordinate1,...
bool isRejected() const
Method used to determine whether this control point is rejected.
void setAdjustedSurfacePoint(SurfacePoint surfacePoint)
Sets the adjusted surface point for this BundleControlPoint.
boost::numeric::ublas::bounded_vector< double, 3 > m_aprioriSigmas
apriori sigmas for point parameters
ControlPoint * m_controlPoint
< pointer to the control point object this represents
QString formatAdjustedSigmaString(SurfacePoint::CoordIndex, int fieldWidth, int precision, bool errorPropagation) const
Formats the adjusted sigma value indicated by the given type code.
QString formatCoordAprioriSigmaString(SurfacePoint::CoordIndex index, int fieldWidth, int precision, bool solveRadius=false) const
Formats the apriori coordinate 1 (latitude or X) sigma value.
boost::numeric::ublas::bounded_vector< double, 3 > & corrections()
Accesses the 3 dimensional ordered vector of correction values associated with coord1,...
boost::numeric::ublas::bounded_vector< double, 3 > & aprioriSigmas()
Accesses the 3 dimensional ordered vector of apriori sigmas (apriori coordinate1, apriori coordinate2...
BundleMeasureQsp addMeasure(ControlMeasure *controlMeasure)
Creates a BundleMeasure from the given ControlMeasure and appends it to this BundleControlPoint's mea...
boost::numeric::ublas::bounded_vector< double, 3 > m_adjustedSigmas
adjusted sigmas for point parameters
void copy(const BundleControlPoint &src)
Copies given BundleControlPoint to this BundleControlPoint.
SurfacePoint::CoordinateType m_coordTypeReports
BundleControlPoint coordinate type.
boost::numeric::ublas::bounded_vector< double, 3 > & adjustedSigmas()
Accesses the 3 dimensional ordered vector of adjusted sigmas (adjusted coordinate1,...
void setWeights(const BundleSettingsQsp settings)
Sets the weights using the given BundleSettings QSharedPointer and a conversion value for meters to r...
QString formatBundleOutputSummaryString(bool errorPropagation) const
Formats an output summary string for this BundleControlPoint.
void setSigmaWeightFromGlobals(double gSigma, int index)
Sets the member sigmas and weights from a global sigma.
int numberOfMeasures() const
Accesses number of measures associated with this BundleControlPoint.
ControlPoint * rawControlPoint() const
Accessor for the raw ControlPoint object used for this BundleControlPoint.
boost::numeric::ublas::bounded_vector< double, 3 > m_weights
weights for point parameters
SparseBlockRowMatrix m_cholmodQMatrix
The CholMod matrix associated with this point.
QString id() const
Accesses the Point ID associated with this BundleControlPoint.
A container class for a ControlMeasure.
a control measurement
A single control point.
double GetResidualRms() const
Get rms of residuals.
Status SetRejected(bool rejected)
Set the jigsawRejected state.
PointType GetType() const
Status SetAdjustedSurfacePoint(SurfacePoint newSurfacePoint)
Set or update the surface point relating to this control point.
PointType
These are the valid 'types' of point.
@ Constrained
A Constrained point is a Control Point whose lat/lon/radius is somewhat established and should not be...
@ Free
A Free point is a Control Point that identifies common measurements between two or more cubes.
@ Fixed
A Fixed point is a Control Point whose lat/lon is well established and should not be changed.
const ControlMeasure * GetMeasure(QString serialNumber) const
Get a control measure based on its cube's serial number.
bool IsCoord2Constrained()
Return bool indicating if 2nd coordinate is Constrained or not.
bool IsCoord1Constrained()
Return bool indicating if 1st coordinate is Constrained or not.
bool IsCoord3Constrained()
Return bool indicating if 3rd coordinate is Constrained or not.
static QString PointTypeToString(PointType type)
Obtain a string representation of a given PointType.
Status ComputeResiduals()
This method computes the BundleAdjust residuals for a point.
QString GetId() const
Return the Id of the control point.
void ZeroNumberOfRejectedMeasures()
Initialize the number of rejected measures to 0.
int GetNumberOfRejectedMeasures() const
Get the number of rejected measures on the control point.
void SetNumberOfRejectedMeasures(int numRejected)
Set (update) the number of rejected measures for the control point.
Displacement is a signed length, usually in meters.
double kilometers() const
Get the displacement in kilometers.
@ Kilometers
The distance is being specified in kilometers.
@ Meters
The distance is being specified in meters.
Distance measurement, usually in meters.
Definition Distance.h:34
double kilometers() const
Get the distance in kilometers.
Definition Distance.cpp:106
@ Kilometers
The distance is being specified in kilometers.
Definition Distance.h:45
@ Meters
The distance is being specified in meters.
Definition Distance.h:43
double meters() const
Get the distance in meters.
Definition Distance.cpp:85
Isis exception class.
Definition IException.h:91
@ Programmer
This error is for when a programmer made an API call that was illegal.
Definition IException.h:146
Adds specific functionality to C++ strings.
Definition IString.h:165
This class is designed to encapsulate the concept of a Latitude.
Definition Latitude.h:51
boost::numeric::ublas::vector< double > Vector
Definition for an Isis::LinearAlgebra::Vector of doubles.
This class is designed to encapsulate the concept of a Longitude.
Definition Longitude.h:40
This class defines a body-fixed surface point.
CoordinateType
Defines the coordinate typ, units, and coordinate index for some of the output methods.
@ Latitudinal
Planetocentric latitudinal (lat/lon/rad) coordinates.
@ Rectangular
Body-fixed rectangular x/y/z coordinates.
Latitude GetLatitude() const
Return the body-fixed latitude for the surface point.
double GetWeight(CoordinateType type, CoordIndex index)
This method returns the weight of a SurfacePoint coordinate Note: At this time a units argument is no...
double MetersToLongitude(double lonLength)
This method returns an angular measure in radians of a distance in the direction of and relative to t...
double LongitudeToMeters(double longitude) const
This method returns a length in meters version of a delta longitude angle in radians relative to the ...
Longitude GetLongitude() const
Return the body-fixed longitude for the surface point.
double GetCoord(CoordinateType type, CoordIndex index, CoordUnits units)
This method returns a coordinate of a SurfacePoint.
double LatitudeToMeters(double latitude) const
This method returns a Displacement of an Angle relative to the current SurfacePoint latitude.
double MetersToLatitude(double latLength)
This method returns an angular measure of a distance in the direction of and relative to the latitude...
Distance GetSigmaDistance(CoordinateType type, CoordIndex index)
This method returns a sigma of a SurfacePoint coordinate as a Distance.
Distance GetLocalRadius() const
Return the radius of the surface point.
This is free and unencumbered software released into the public domain.
Definition Apollo.h:16
QString toString(bool boolToConvert)
Global function to convert a boolean to a string.
Definition IString.cpp:211
const double DEG2RAD
Multiplier for converting from degrees to radians.
Definition Constants.h:43
const double Null
Value for an Isis Null pixel.
bool IsSpecial(const double d)
Returns if the input pixel is special.
const double RAD2DEG
Multiplier for converting from radians to degrees.
Definition Constants.h:44
QSharedPointer< BundleMeasure > BundleMeasureQsp
Definition for BundleMeasureQsp, a shared pointer to a BundleMeasure.