in opensfm/src/bundle/error/projection_errors.h [62:146]
bool Evaluate(double const* const* parameters, double* residuals,
double** jacobians) const {
const double* camera = parameters[0];
const double* rig_instance = parameters[1];
const double* rig_camera = parameters[2];
const double* point = parameters[3];
constexpr int PointSize = 3;
double transformed[PointSize];
double predicted[Size];
/* Error only */
if (!jacobians) {
geometry::PoseFunctor::Forward(point, rig_instance, &transformed[0]);
geometry::PoseFunctor::Forward(&transformed[0], rig_camera,
&transformed[0]);
geometry::Dispatch<geometry::ProjectFunction>(type_, transformed, camera,
predicted);
} /* Jacobian + Error */
else {
constexpr int CameraSize = C;
constexpr int PoseSize = 6;
double all_params[PoseSize + PoseSize + CameraSize];
for (int i = 0; i < PoseSize; ++i) {
all_params[i] = rig_instance[i];
}
for (int i = 0; i < PoseSize; ++i) {
all_params[PoseSize + i] = rig_camera[i];
}
for (int i = 0; i < CameraSize; ++i) {
all_params[2 * PoseSize + i] = camera[i];
}
constexpr int StrideFull = PointSize + CameraSize + 2 * PoseSize;
double jacobian[Size * StrideFull];
geometry::Dispatch<geometry::ProjectRigPoseDerivatives>(
type_, point, &all_params[0], &predicted[0], &jacobian[0]);
// Unfold big jacobian stored as | point | jac_rig_instance |
// jac_rig_camera | camera | per block We also take the opportunity to
// apply the scale
double *jac_camera = jacobians[0], *jac_rig_instance = jacobians[1],
*jac_rig_camera = jacobians[2], *jac_point = jacobians[3];
Eigen::Map<Eigen::Matrix<double, Size, StrideFull, Eigen::RowMajor>>
map_jac_big(jacobian);
if (jac_point) {
Eigen::Map<Eigen::Matrix<double, Size, PointSize, Eigen::RowMajor>>
map_jac_point(jac_point);
map_jac_point =
scale_ * map_jac_big.template block<Size, PointSize>(0, 0);
}
if (jac_rig_instance) {
Eigen::Map<Eigen::Matrix<double, Size, PoseSize, Eigen::RowMajor>>
map_jac_rig_instance(jac_rig_instance);
map_jac_rig_instance =
scale_ * map_jac_big.template block<Size, PoseSize>(0, PointSize);
}
if (jac_rig_camera) {
Eigen::Map<Eigen::Matrix<double, Size, PoseSize, Eigen::RowMajor>>
map_jac_rig_camera(jac_rig_camera);
map_jac_rig_camera =
scale_ *
map_jac_big.template block<Size, PoseSize>(0, PointSize + PoseSize);
}
if (jac_camera) {
// Eigen doesn't like vectors as 1-dim matrices (CameraSize == 1), using
// simple assignments instead of Eigen's Map
for (int i = 0; i < Size; ++i) {
for (int j = 0; j < CameraSize; ++j) {
jac_camera[i * CameraSize + j] =
scale_ *
jacobian[i * StrideFull + PointSize + 2 * PoseSize + j];
}
}
}
}
// The error is the difference between the predicted and observed position
for (int i = 0; i < Size; ++i) {
residuals[i] = scale_ * (predicted[i] - observed_[i]);
}
return true;
}