Isis 3 Programmer Reference
BundleLidarRangeConstraint.cpp
1#include "BundleLidarRangeConstraint.h"
2
3// Qt Library
4#include <QDebug>
5
6// Boost uBLAS
7#include <boost/numeric/ublas/vector_proxy.hpp>
8#include <boost/numeric/ublas/matrix_proxy.hpp>
9
10// Isis Library
11#include "Camera.h"
12#include "CameraGroundMap.h"
13#include "IsisBundleObservation.h"
14#include "SpicePosition.h"
15
16using namespace boost::numeric::ublas;
17
18namespace Isis {
19
27 BundleMeasureQsp measure) {
28 m_lidarControlPoint = lidarControlPoint;
29 m_simultaneousMeasure = measure;
30 m_bundleObservation = measure->parentBundleObservation();
32
33 if (m_rangeObserved <= 0) {
34 QString msg ="In BundleLidarRangeConstraint::BundleLidarRangeConstraint():"
35 "observed range for lidar point must be positive (Point Id: "
36 + measure->parentControlPoint()->id() + ")\n.";
37 throw IException(IException::Programmer, msg, _FILEINFO_);
38 }
39
40 m_rangeObservedSigma = m_lidarControlPoint->sigmaRange() * 0.001; // converting from m to km
41
42 if (m_rangeObservedSigma <= 0) {
43 QString msg ="In BundleLidarRangeConstraint::BundleLidarRangeConstraint():"
44 "observed range sigma for lidar point must be positive (Point Id: "
45 + measure->parentControlPoint()->id() + ")\n.";
46 throw IException(IException::Programmer, msg, _FILEINFO_);
47 }
48
50 m_adjustedSigma = 0.0;
51 m_dX = m_dY = m_dZ = 0.0;
52
53 // Check that the simultaneous image has an ISIS camera
54 if (m_simultaneousMeasure->camera()->GetCameraType() == Camera::Csm) {
55 QString msg = "Cannot apply a Lidar range constraint to a CSM camera model"
56 "(Point Id: "
57 + measure->parentControlPoint()->id() + ", Measure Serial:"
58 + measure->cubeSerialNumber() + ").\n";
59 throw IException(IException::Programmer, msg, _FILEINFO_);
60 }
61
62 // initialize computed range
64 }
65
66
72
73
82 m_dX = src.m_dX;
83 m_dY = src.m_dY;
84 m_dZ = src.m_dZ;
85 m_rangeObserved = src.m_rangeObserved;
86 m_rangeComputed = src.m_rangeComputed;
87 m_rangeObservedSigma = src.m_rangeObservedSigma;
88 m_rangeObservedWeightSqrt = src.m_rangeObservedWeightSqrt;
89 m_adjustedSigma = src.m_adjustedSigma;
90 m_vtpv = src.m_vtpv;
91 }
92
93
106
107 // Prevent self assignment
108 if (this != &src) {
109 m_dX = src.m_dX;
110 m_dY = src.m_dY;
111 m_dZ = src.m_dZ;
112 m_rangeObserved = src.m_rangeObserved;
113 m_rangeComputed = src.m_rangeComputed;
114 m_rangeObservedSigma = src.m_rangeObservedSigma;
115 m_rangeObservedWeightSqrt = src.m_rangeObservedWeightSqrt;
116 m_adjustedSigma = src.m_adjustedSigma;
117 m_vtpv = src.m_vtpv;
118 }
119
120 return *this;
121 }
122
123
135
136 // establish camera model for simultaneous measure
137 m_simultaneousMeasure->setImage();
138
139 // get spacecraft coordinates in J2000 reference system
140 std::vector<double> camPositionJ2K
141 = m_simultaneousMeasure->camera()->instrumentPosition()->Coordinate();
142
143 // body rotation "ReferenceVector" rotates spacecraft coordinates from J2000 to body-fixed
144 std::vector<double> camPositionBodyFixed
145 = m_simultaneousMeasure->camera()->bodyRotation()->ReferenceVector(camPositionJ2K);
146
147 // current body fixed XYZ coordinates of lidar control point
148 SurfacePoint adjustedSurfacePoint = m_lidarControlPoint->GetAdjustedSurfacePoint();
149 std::vector<double> pointBodyFixed(3);
150 pointBodyFixed[0] = adjustedSurfacePoint.GetX().kilometers();
151 pointBodyFixed[1] = adjustedSurfacePoint.GetY().kilometers();
152 pointBodyFixed[2] = adjustedSurfacePoint.GetZ().kilometers();
153
154 // compute and store dX, dY, dZ between body-fixed coordinates of spacecraft and lidar point
155 m_dX = camPositionBodyFixed[0] - pointBodyFixed[0];
156 m_dY = camPositionBodyFixed[1] - pointBodyFixed[1];
157 m_dZ = camPositionBodyFixed[2] - pointBodyFixed[2];
158
159 m_rangeComputed = sqrt(m_dX*m_dX+m_dY*m_dY+m_dZ*m_dZ);
160
161 if (m_rangeComputed <= 0.0) {
162 QString msg = "In BundleLidarRangeConstraint::computeRange(): "
163 "m_rangeComputed must be positive\n";
164 throw IException(IException::Programmer, msg, _FILEINFO_);
165 }
166 }
167
168
186
187 if (m_simultaneousMeasure->isRejected()) {
188 return false;
189 }
190
191 // establish camera model for simultaneous measure
192 m_simultaneousMeasure->setImage();
193
194 // time of current location of simultaneous measure
195 double scaledTime = m_simultaneousMeasure->camera()->instrumentPosition()->scaledTime();
196
197 // current body fixed XYZ coordinates of lidar control point
198 SurfacePoint adjustedSurfacePoint = m_lidarControlPoint->GetAdjustedSurfacePoint();
199
200 static LinearAlgebra::Matrix coeff_range_image;
201 static LinearAlgebra::Matrix coeff_range_point3D(1,3);
202 static LinearAlgebra::Vector coeff_range_RHS(1);
203
204 // index into normal equations for this measure
205 int positionBlockIndex = m_simultaneousMeasure->observationIndex();
206
207 // resize coeff_range_image matrix if necessary
209 if (!isisObservation) {
210 QString msg = "Failed to cast BundleObservation to IsisBundleObservation when applying "
211 "lidar constraint (Point Id: "
212 + m_simultaneousMeasure->parentControlPoint()->id() + ", Measure Serial:"
213 + m_simultaneousMeasure->cubeSerialNumber() + ").\n";
214 throw IException(IException::Programmer, msg, _FILEINFO_);
215 }
216 int numPositionParameters = isisObservation->numberPositionParameters();
217 if ((int) coeff_range_image.size2() != numPositionParameters) {
218 coeff_range_image.resize(1, numPositionParameters, false);
219 }
220
221 coeff_range_image.clear();
222 coeff_range_point3D.clear();
223 coeff_range_RHS.clear();
224
225 // get matrix that rotates spacecraft from J2000 to body-fixed
226 std::vector<double> matrixTargetToJ2K =
227 m_simultaneousMeasure->camera()->bodyRotation()->Matrix();
228
229 double m11 = matrixTargetToJ2K[0];
230 double m12 = matrixTargetToJ2K[1];
231 double m13 = matrixTargetToJ2K[2];
232 double m21 = matrixTargetToJ2K[3];
233 double m22 = matrixTargetToJ2K[4];
234 double m23 = matrixTargetToJ2K[5];
235 double m31 = matrixTargetToJ2K[6];
236 double m32 = matrixTargetToJ2K[7];
237 double m33 = matrixTargetToJ2K[8];
238
239 // a1, a2, a3 are auxiliary variables used in partial derivatives
240 double a1 = -(m11*m_dX + m21*m_dY + m31*m_dZ)/m_rangeComputed;
241 double a2 = -(m12*m_dX + m22*m_dY + m32*m_dZ)/m_rangeComputed;
242 double a3 = -(m13*m_dX + m23*m_dY + m33*m_dZ)/m_rangeComputed;
243
244 // partials with respect to camera body fixed X polynomial coefficients
245 double c = 1.0;
246 int numPositionParametersPerCoordinate = numPositionParameters/3;
247 int index = 0;
248 for (int i = 0; i < numPositionParametersPerCoordinate; i++) {
249 coeff_range_image(0,index) = a1*c;
250 c *= scaledTime;
251 index++;
252 }
253
254 // partials with respect to camera body fixed Y polynomial coefficients
255 c = 1.0;
256 for (int i = 0; i < numPositionParametersPerCoordinate; i++) {
257 coeff_range_image(0,index) = a2*c;
258 c *= scaledTime;
259 index++;
260 }
261
262 // partials with respect to camera body fixed Z polynomial coefficients
263 c = 1.0;
264 for (int i = 0; i < numPositionParametersPerCoordinate; i++) {
265 coeff_range_image(0,index) = a3*c;
266 c *= scaledTime;
267 index++;
268 }
269
270 // partials w/r to point
271 double lat = adjustedSurfacePoint.GetLatitude().radians();
272 double lon = adjustedSurfacePoint.GetLongitude().radians();
273 double radius = adjustedSurfacePoint.GetLocalRadius().kilometers();
274
275 double sinlat = sin(lat);
276 double coslat = cos(lat);
277 double sinlon = sin(lon);
278 double coslon = cos(lon);
279
280 // partials with respect to point latitude, longitude, and radius
281 coeff_range_point3D(0,0)
282 = radius*(-sinlat*coslon*m_dX - sinlat*sinlon*m_dY + coslat*m_dZ)/m_rangeComputed;
283 coeff_range_point3D(0,1)
284 = radius*(-coslat*sinlon*m_dX + coslat*coslon*m_dY)/m_rangeComputed;
285 coeff_range_point3D(0,2)
286 = (coslat*coslon*m_dX + coslat*sinlon*m_dY + sinlat*m_dZ)/m_rangeComputed;
287
288 // right hand side (observed distance - computed distance)
289 coeff_range_RHS(0) = m_rangeObserved - m_rangeComputed;
290
291 // multiply coefficients by observation weight
292 // TODO: explain negative sign here
293 coeff_range_image *= -m_rangeObservedWeightSqrt;
294 coeff_range_point3D *= -m_rangeObservedWeightSqrt;
295 coeff_range_RHS *= m_rangeObservedWeightSqrt;
296
297 // add range condition contribution to N11 portion of normal equations matrix
298 matrix_range<LinearAlgebra::Matrix> normal_range(
299 *(*normalsMatrix[positionBlockIndex])[positionBlockIndex],
300 range(0, coeff_range_image.size2()),
301 range(0, coeff_range_image.size2()));
302
303 normal_range += prod(trans(coeff_range_image), coeff_range_image);
304
305 // add range condition contribution to N12 portion of normal equations matrix
306 matrix_range<LinearAlgebra::Matrix> N12_range(
307 *N12[positionBlockIndex],
308 range(0, coeff_range_image.size2()),
309 range(0, coeff_range_point3D.size2()));
310
311 N12_range += prod(trans(coeff_range_image), coeff_range_point3D);
312
313 // contribution to n1 vector
314 int startColumn = normalsMatrix.at(positionBlockIndex)->startColumn();
315 vector_range<LinearAlgebra::VectorCompressed >
316 n1_range (n1, range (startColumn, startColumn+coeff_range_image.size2()));
317
318 n1_range += prod(trans(coeff_range_image), coeff_range_RHS);
319
320 // form N22
321 N22 += prod(trans(coeff_range_point3D), coeff_range_point3D);
322
323 // contribution to n2 vector
324 n2 += prod(trans(coeff_range_point3D), coeff_range_RHS);
325
326 return true;
327 }
328
329
339
340
350
351
361
362
372
373
381 if (m_simultaneousMeasure->isRejected()) {
382 return 0.0;
383 }
384
385 // update computed range
386 // Note that this prepares us for the next iteration of the bundle adjustment
387 computeRange();
388
389 // residual
390 double v = m_rangeObserved - m_rangeComputed;
391
392 // contribution to weighted sum of squares of residuals
394
395 return m_vtpv;
396 }
397
398
408
409
420
421 QString outstr;
422
423 FileName imageFileName = m_simultaneousMeasure->parentBundleObservation()->imageNames().at(0);
424 QString imageName = imageFileName.baseName();
425
426 // measured apriori adjusted adjusted
427 // range sigma range sigma residual
428 // point id image (km) (km) (km) (km) (km)
429
430 if (errorProp) {
431 outstr = QString("%1,%2,%3,%4,%5,%6,%7\n").arg(m_lidarControlPoint->GetId(), 16)
432 .arg(imageName, 16)
433 .arg(m_rangeObserved, -16, 'f', 8)
434 .arg(m_rangeObservedSigma, -16, 'f', 2)
435 .arg(m_rangeComputed, -16, 'f', 8)
436 .arg(m_adjustedSigma, -16, 'f', 6)
437 .arg(m_rangeObserved - m_rangeComputed, -16, 'f', 8);
438 }
439 else {
440 outstr = QString("%1,%2,%3,%4,%5,%6\n").arg(m_lidarControlPoint->GetId())
441 .arg(imageName)
442 .arg(m_rangeObserved)
444 .arg(m_rangeComputed)
446 }
447
448 return outstr;
449 }
450}
double radians() const
Convert an angle to a double.
Definition Angle.h:226
Implements range constraint between image position and lidar point acquired simultaneously with the i...
double rangeObservedSigma()
Return sigma of range observation.
double m_rangeObserved
! deltas between spacecraft & lidar point in body-fixed coordinates
double m_dX
! 2D image point corresponding to 3D lidar point on surface.
double m_vtpv
Weighted sum-of-squares of residual.
QString formatBundleOutputString(bool errorProp=false)
Creates & returns formatted QString for lidar range constraint to output to bundleout_lidar....
BundleLidarRangeConstraint(LidarControlPointQsp lidarControlPoint, BundleMeasureQsp measure)
constructor
BundleLidarRangeConstraint & operator=(const BundleLidarRangeConstraint &src)
Assignment operator.
double rangeComputed()
Return computed lidar range.
LidarControlPointQsp m_lidarControlPoint
Parent lidar control point.
BundleObservationQsp m_bundleObservation
BundleObservation associated with measure.
double m_rangeObservedSigma
Uncertainty of observed range.
bool applyConstraint(SparseBlockMatrix &normalsMatrix, LinearAlgebra::MatrixUpperTriangular &N22, SparseBlockColumnMatrix &N12, LinearAlgebra::VectorCompressed &n1, LinearAlgebra::Vector &n2)
Computes partial derivatives of range condition equation and adds contribution into the bundle adjust...
double m_rangeObservedWeightSqrt
Square-root of observed range weight.
void errorPropagation()
TODO: to be completed.
double vtpv()
Return current value of weighted sum-of-squares of residual.
double m_adjustedSigma
Adjusted uncertainty of range.
double rangeObserved()
Return observed lidar range.
double rangeAdjustedSigma()
Return adjusted sigma of range observation.
double m_rangeComputed
Computed range from distance condition.
void computeRange()
Compute range between spacecraft & lidar point on surface given the current values of the spacecraft ...
@ Csm
Community Sensor Model Camera.
Definition Camera.h:365
double kilometers() const
Get the displacement in kilometers.
double kilometers() const
Get the distance in kilometers.
Definition Distance.cpp:106
File name manipulation and expansion.
Definition FileName.h:100
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
Class for observations that use ISIS camera models in bundle adjustment.
boost::numeric::ublas::compressed_vector< double > VectorCompressed
Definition for an Isis::LinearAlgebra::VectorCompressed of doubles.
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.
boost::numeric::ublas::symmetric_matrix< double, boost::numeric::ublas::upper > MatrixUpperTriangular
Definition for an Isis::LinearAlgebra::MatrixUpperTriangular of doubles with an upper configuration.
SparseBlockColumnMatrix.
This class defines a body-fixed surface point.
Latitude GetLatitude() const
Return the body-fixed latitude for the surface point.
Longitude GetLongitude() const
Return the body-fixed longitude for the surface point.
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
QSharedPointer< IsisBundleObservation > IsisBundleObservationQsp
Typdef for IsisBundleObservation QSharedPointer.