Isis 3 Programmer Reference
CsmBundleObservation.cpp
1
7/* SPDX-License-Identifier: CC0-1.0 */
8
9#include "CsmBundleObservation.h"
10
11#include <QDebug>
12#include <QString>
13#include <QStringList>
14#include <QVector>
15
16#include "BundleImage.h"
17#include "BundleControlPoint.h"
18#include "BundleObservationSolveSettings.h"
19#include "BundleTargetBody.h"
20#include "Camera.h"
21#include "CSMCamera.h"
22#include "LinearAlgebra.h"
23#include "SpicePosition.h"
24#include "SpiceRotation.h"
25
26using namespace std;
27
28namespace Isis {
29
35
36
47 QString instrumentId, BundleTargetBodyQsp bundleTargetBody) : BundleObservation(image, observationNumber, instrumentId, bundleTargetBody) {
48 if (bundleTargetBody) {
49 QString msg = "Target body parameters cannot be solved for with CSM observations.";
50 throw IException(IException::User, msg, _FILEINFO_);
51 }
52 }
53
54
61 m_solveSettings = src.m_solveSettings;
62 m_paramIndices = src.m_paramIndices;
63 }
64
65
73
74
85 if (&src != this) {
86 m_solveSettings = src.m_solveSettings;
87 m_paramIndices = src.m_paramIndices;
88 }
89 return *this;
90 }
91
92
103
104 CSMCamera *csmCamera = dynamic_cast<CSMCamera*>(front()->camera());
105
106 m_paramIndices.clear();
107 m_weights.clear();
108 m_corrections.clear();
109 m_adjustedSigmas.clear();
110
111 if (m_solveSettings->csmSolveOption() == BundleObservationSolveSettings::Set) {
112 m_paramIndices = csmCamera->getParameterIndices(m_solveSettings->csmParameterSet());
113 }
114 else if (m_solveSettings->csmSolveOption() == BundleObservationSolveSettings::Type) {
115 m_paramIndices = csmCamera->getParameterIndices(m_solveSettings->csmParameterType());
116 }
117 else if (m_solveSettings->csmSolveOption() == BundleObservationSolveSettings::List) {
118 m_paramIndices = csmCamera->getParameterIndices(m_solveSettings->csmParameterList());
119 }
120 else {
121 return false;
122 }
123
124 int nParams = m_paramIndices.size();
125
126 m_weights.resize(nParams);
127 m_corrections.resize(nParams);
128 m_adjustedSigmas.resize(nParams);
129 m_aprioriSigmas.resize(nParams);
130
131 for (int i = 0; i < nParams; i++) {
132 m_aprioriSigmas[i] = csmCamera->getParameterCovariance(m_paramIndices[i], m_paramIndices[i]);
133 }
134
135 return true;
136 }
137
138
148
149
164 // Check that the correction vector is the correct size
165 if (corrections.size() != m_paramIndices.size()) {
166 QString msg = "Invalid correction vector passed to observation.";
167 IException(IException::Programmer, msg, _FILEINFO_);
168 }
169
170 // Apply the corrections to the CSM camera
171 CSMCamera *csmCamera = dynamic_cast<CSMCamera*>(front()->camera());
172 for (size_t i = 0; i < corrections.size(); i++) {
173 csmCamera->applyParameterCorrection(m_paramIndices[i], corrections[i]);
174 }
175
176 // Accumulate the total corrections
177 m_corrections += corrections;
178
179 return true;
180 }
181
182
194
195
205 void CsmBundleObservation::bundleOutputString(std::ostream &fpOut, bool errorPropagation) {
206
207 char buf[4096];
208
209 QVector<double> finalParameterValues;
210 CSMCamera *csmCamera = dynamic_cast<CSMCamera*>(front()->camera());
211
212 int nParameters = numberParameters();
213
214 QStringList parameterNamesList;
215 QStringList parameterUnitList;
216
217 for (int i = 0; i < nParameters; i++) {
218 parameterNamesList.append(csmCamera->getParameterName(m_paramIndices[i]));
219 parameterUnitList.append(csmCamera->getParameterUnits(m_paramIndices[i]));
220 finalParameterValues.append(csmCamera->getParameterValue(m_paramIndices[i]));
221 }
222
223
224 // Set up default values when we are using default position
225 QString sigma;
226 QString adjustedSigma;
227 double correction;
228
229 for (int i = 0; i < nParameters; i++) {
230
231 correction = m_corrections(i);
232 adjustedSigma = QString::number(m_adjustedSigmas[i], 'f', 8);
233 sigma = (IsSpecial(m_aprioriSigmas[i]) ? "FREE" : toString(m_aprioriSigmas[i], 8));
234
235 snprintf(buf, sizeof(buf), "%.11s", parameterNamesList.at(i).toStdString().c_str());
236 fpOut << buf;
237 snprintf(buf, sizeof(buf), "%18.8lf ", finalParameterValues[i] - correction);
238 fpOut << buf;
239 snprintf(buf, sizeof(buf), "%20.8lf ", correction);
240 fpOut << buf;
241 snprintf(buf, sizeof(buf), "%23.8lf ", finalParameterValues[i]);
242 fpOut << buf;
243 snprintf(buf, sizeof(buf), " ");
244 fpOut << buf;
245 snprintf(buf, sizeof(buf), "%6s", sigma.toStdString().c_str());
246 fpOut << buf;
247 snprintf(buf, sizeof(buf), " ");
248 fpOut << buf;
249 if (errorPropagation) {
250 snprintf(buf, sizeof(buf), "%s", adjustedSigma.toStdString().c_str());
251 }
252 else {
253 snprintf(buf, sizeof(buf), "%s","N/A");
254 }
255 fpOut << buf;
256 snprintf(buf, sizeof(buf), " ");
257 fpOut << buf;
258 snprintf(buf, sizeof(buf), "%s\n", parameterUnitList.at(i).toStdString().c_str());
259 fpOut << buf;
260
261 }
262 }
263
274 QString CsmBundleObservation::bundleOutputCSV(bool errorPropagation) {
275 QString finalqStr = "";
276 CSMCamera *csmCamera = dynamic_cast<CSMCamera*>(front()->camera());
277
278 for (size_t i = 0; i < m_paramIndices.size(); i++) {
279 double finalValue = csmCamera->getParameterValue(m_paramIndices[i]);
280 finalqStr += toString(finalValue - m_corrections[i]) + ",";
281 finalqStr += toString(m_corrections[i]) + ",";
282 finalqStr += toString(finalValue) + ",";
283 finalqStr += toString(m_aprioriSigmas[i], 8) + ",";
284 if (errorPropagation) {
285 finalqStr += QString::number(m_adjustedSigmas[i], 'f', 8) + ",";
286 }
287 else {
288 finalqStr += "N/A,";
289 }
290 }
291
292 return finalqStr;
293 }
294
295
306 QStringList paramList;
307 CSMCamera *csmCamera = dynamic_cast<CSMCamera*>(front()->camera());
308
309 for (int paramIndex : m_paramIndices) {
310 paramList.push_back(csmCamera->getParameterName(paramIndex));
311 }
312
313 return paramList;
314 }
315
330 if (bundleTargetBody) {
331 QString msg = "Target body parameters cannot be solved for with CSM observations.";
332 throw IException(IException::User, msg, _FILEINFO_);
333 }
334 return false;
335 }
336
337
351 coeffImage.clear();
352
353 CSMCamera *csmCamera = dynamic_cast<CSMCamera*>(measure.camera());
354 SurfacePoint groundPoint = measure.parentControlPoint()->adjustedSurfacePoint();
355
356 // Loop over parameters and populate matrix
357 for (size_t i = 0; i < m_paramIndices.size(); i++) {
358 vector<double> partials = csmCamera->getSensorPartials(m_paramIndices[i], groundPoint);
359 coeffImage(0, i) = partials[1];
360 coeffImage(1, i) = partials[0];
361 }
362
363 return true;
364 }
365
366
382 coeffPoint3D.clear();
383
384 CSMCamera *measureCamera = dynamic_cast<CSMCamera*>(measure.camera());
385
386 // do ground partials
387 SurfacePoint groundPoint = measure.parentControlPoint()->adjustedSurfacePoint();
388 vector<double> groundPartials = measureCamera->GroundPartials(groundPoint);
389
390 if (coordType == SurfacePoint::Rectangular) {
391 // groundPartials is:
392 // line WRT x
393 // line WRT y
394 // line WRT z
395 // sample WRT x
396 // sample WRT y
397 // sample WRT z
398 // Scale from WRT m to WRT Km
399 coeffPoint3D(1,0) = groundPartials[0] * 1000;
400 coeffPoint3D(1,1) = groundPartials[1] * 1000;
401 coeffPoint3D(1,2) = groundPartials[2] * 1000;
402 coeffPoint3D(0,0) = groundPartials[3] * 1000;
403 coeffPoint3D(0,1) = groundPartials[4] * 1000;
404 coeffPoint3D(0,2) = groundPartials[5] * 1000;
405 }
406 else if (coordType == SurfacePoint::Latitudinal) {
407 std::vector<double> latDerivative = groundPoint.LatitudinalDerivative(SurfacePoint::One);
408 std::vector<double> lonDerivative = groundPoint.LatitudinalDerivative(SurfacePoint::Two);
409 std::vector<double> radDerivative = groundPoint.LatitudinalDerivative(SurfacePoint::Three);
410
411 // Line w.r.t (lat, lon, radius)
412 coeffPoint3D(1,0) = 1000 * (groundPartials[0]*latDerivative[0] + groundPartials[1]*latDerivative[1] + groundPartials[2]*latDerivative[2]);
413 coeffPoint3D(1,1) = 1000 * (groundPartials[0]*lonDerivative[0] + groundPartials[1]*lonDerivative[1] + groundPartials[2]*lonDerivative[2]);
414 coeffPoint3D(1,2) = 1000 * (groundPartials[0]*radDerivative[0] + groundPartials[1]*radDerivative[1] + groundPartials[2]*radDerivative[2]);
415
416 // Sample w.r.t (lat, lon, radius)
417 coeffPoint3D(0,0) = 1000 * (groundPartials[3]*latDerivative[0] + groundPartials[4]*latDerivative[1] + groundPartials[5]*latDerivative[2]);
418 coeffPoint3D(0,1) = 1000 * (groundPartials[3]*lonDerivative[0] + groundPartials[4]*lonDerivative[1] + groundPartials[5]*lonDerivative[2]);
419 coeffPoint3D(0,2) = 1000 * (groundPartials[3]*radDerivative[0] + groundPartials[4]*radDerivative[1] + groundPartials[5]*radDerivative[2]);
420 }
421 else {
422 IString msg ="Unknown surface point coordinate type enum [" + toString(coordType) + "]." ;
423 throw IException(IException::Programmer, msg, _FILEINFO_);
424 }
425 return true;
426 }
427
428
442 // Clear old values
443 coeffRHS.clear();
444
445 Camera *measureCamera = measure.camera();
446 BundleControlPoint* point = measure.parentControlPoint();
447
448 // Get ground-to-image computed coordinates for this point.
449 if (!(measureCamera->SetGround(point->adjustedSurfacePoint()))) {
450 QString msg = "Unable to map apriori surface point for measure ";
451 msg += measure.cubeSerialNumber() + " on point " + point->id() + " back into image.";
452 throw IException(IException::User, msg, _FILEINFO_);
453 }
454 double computedSample = measureCamera->Sample();
455 double computedLine = measureCamera->Line();
456
457 // The RHS is the difference between the measured coordinates on the image
458 // and the coordinates calculated by the ground to image call.
459 double deltaSample = measure.sample() - computedSample;
460 double deltaLine = measure.line() - computedLine;
461
462 coeffRHS(0) = deltaSample;
463 coeffRHS(1) = deltaLine;
464
465 return true;
466 }
467
468
482 return deltaVal;
483 }
484}
This class holds information about a control point that BundleAdjust needs to run correctly.
SurfacePoint adjustedSurfacePoint() const
Accesses the adjusted SurfacePoint associated with this BundleControlPoint.
QString id() const
Accesses the Point ID associated with this BundleControlPoint.
A container class for a ControlMeasure.
Abstract base class for an observation in bundle adjustment.
LinearAlgebra::Vector m_aprioriSigmas
A posteriori (adjusted) parameter sigmas.
LinearAlgebra::Vector m_adjustedSigmas
A posteriori (adjusted) parameter sigmas.
LinearAlgebra::Vector m_weights
Parameter weights. Cumulative parameter correction vector.
This class is used to modify and manage solve settings for 1 to many BundleObservations.
@ Set
Solve for all CSM parameters belonging to a specific set.
@ Type
Solve for all CSM parameters of a specific type.
@ List
Solve for an explicit list of CSM parameters.
double getParameterValue(int index)
Get the value of a parameter.
void applyParameterCorrection(int index, double correction)
Adjust the value of a parameter.
Class for observations that use CSM camera models in bundle adjustment.
bool computeRHSPartials(LinearAlgebra::Vector &coeffRHS, BundleMeasure &measure)
Calculates the sample, line residuals between the values measured in the image and the ground-to-imag...
CsmBundleObservation & operator=(const CsmBundleObservation &src)
Assignment operator.
int numberParameters()
Returns the number of total parameters there are for solving.
QString bundleOutputCSV(bool errorPropagation)
Creates and returns a formatted QString representing the bundle coefficients and parameters in csv fo...
bool computeTargetPartials(LinearAlgebra::Matrix &coeffTarget, BundleMeasure &measure, BundleSettingsQsp &bundleSettings, BundleTargetBodyQsp &bundleTargetBody)
Cannot compute target body parameters for a CSM observation, so always throws an exception.
bool computeImagePartials(LinearAlgebra::Matrix &coeffImage, BundleMeasure &measure)
Calculates the sensor partials with respect to the solve parameters and populates the coeffImage matr...
bool applyParameterCorrections(LinearAlgebra::Vector corrections)
Applies the parameter corrections.
const BundleObservationSolveSettingsQsp solveSettings()
Accesses the solve settings.
std::vector< int > m_paramIndices
The indices of the parameters the observation is solving for.
virtual QStringList parameterList()
Returns the list of observation parameter names.
void bundleOutputString(std::ostream &fpOut, bool errorPropagation)
Takes in an open std::ofstream and writes out information which goes into the bundleout....
bool computePoint3DPartials(LinearAlgebra::Matrix &coeffPoint3D, BundleMeasure &measure, SurfacePoint::CoordinateType coordType)
Calculates the ground partials for the line, sample currently set in the sensor model.
virtual bool setSolveSettings(BundleObservationSolveSettings solveSettings)
Set solve parameters.
CsmBundleObservation()
Constructs a CsmBundleObservation initialized to a default state.
double computeObservationValue(BundleMeasure &measure, double deltaVal)
Returns the observed value in (sample, line) coordinates.
BundleObservationSolveSettingsQsp m_solveSettings
Solve settings for this observation.
Isis exception class.
Definition IException.h:91
@ User
A type of error that could only have occurred due to a mistake on the user's part (e....
Definition IException.h:126
@ 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
boost::numeric::ublas::vector< double > Vector
Definition for an Isis::LinearAlgebra::Vector of doubles.
boost::numeric::ublas::matrix< double > Matrix
Definition for an Isis::LinearAlgebra::Matrix of doubles.
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.
std::vector< double > LatitudinalDerivative(CoordIndex index)
Compute partial derivative of the conversion of the latitudinal coordinates to body-fixed rectangular...
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
QSharedPointer< BundleObservationSolveSettings > BundleObservationSolveSettingsQsp
Definition for BundleObservationSolveSettingsQsp, a QSharedPointer to a BundleObservationSolveSetting...
bool IsSpecial(const double d)
Returns if the input pixel is special.
Namespace for the standard library.