Migrate examples to use Manifolds

Also change NULL to nullptr.

Change-Id: I80a2328185d7891f61e07e64d5c1b59e74588ac7
This commit is contained in:
Sameer Agarwal
2022-01-18 16:26:47 -08:00
parent 19eef54fc2
commit 77c0c4d09c
23 changed files with 121 additions and 113 deletions
+2 -2
View File
@@ -73,7 +73,7 @@ double Median(std::vector<double>* data) {
BALProblem::BALProblem(const std::string& filename, bool use_quaternions) {
FILE* fptr = fopen(filename.c_str(), "r");
if (fptr == NULL) {
if (fptr == nullptr) {
LOG(FATAL) << "Error: unable to open file " << filename;
return;
};
@@ -137,7 +137,7 @@ BALProblem::BALProblem(const std::string& filename, bool use_quaternions) {
void BALProblem::WriteToFile(const std::string& filename) const {
FILE* fptr = fopen(filename.c_str(), "w");
if (fptr == NULL) {
if (fptr == nullptr) {
LOG(FATAL) << "Error: unable to open file " << filename;
return;
};
+8 -12
View File
@@ -98,8 +98,7 @@ DEFINE_string(ordering, "automatic", "Options are: automatic, user.");
DEFINE_bool(use_quaternions, false, "If true, uses quaternions to represent "
"rotations. If false, angle axis is used.");
DEFINE_bool(use_local_parameterization, false, "For quaternions, use a local "
"parameterization.");
DEFINE_bool(use_manifolds, false, "For quaternions, use a manifold.");
DEFINE_bool(robustify, false, "Use a robust loss function.");
DEFINE_double(eta, 1e-2, "Default value for eta. Eta determines the "
@@ -293,7 +292,7 @@ void BuildProblem(BALProblem* bal_problem, Problem* problem) {
// If enabled use Huber's loss function.
LossFunction* loss_function =
CERES_GET_FLAG(FLAGS_robustify) ? new HuberLoss(1.0) : NULL;
CERES_GET_FLAG(FLAGS_robustify) ? new HuberLoss(1.0) : nullptr;
// Each observation correponds to a pair of a camera and a point
// which are identified by camera_index()[i] and point_index()[i]
@@ -305,13 +304,11 @@ void BuildProblem(BALProblem* bal_problem, Problem* problem) {
}
if (CERES_GET_FLAG(FLAGS_use_quaternions) &&
CERES_GET_FLAG(FLAGS_use_local_parameterization)) {
LocalParameterization* camera_parameterization =
new ProductParameterization(new QuaternionParameterization(),
new IdentityParameterization(6));
CERES_GET_FLAG(FLAGS_use_manifolds)) {
Manifold* camera_manifold =
new ProductManifold(new QuaternionManifold(), new EuclideanManifold(6));
for (int i = 0; i < bal_problem->num_cameras(); ++i) {
problem->SetParameterization(cameras + camera_block_size * i,
camera_parameterization);
problem->SetManifold(cameras + camera_block_size * i, camera_manifold);
}
}
}
@@ -358,9 +355,8 @@ int main(int argc, char** argv) {
}
CHECK(CERES_GET_FLAG(FLAGS_use_quaternions) ||
!CERES_GET_FLAG(FLAGS_use_local_parameterization))
<< "--use_local_parameterization can only be used with "
<< "--use_quaternions.";
!CERES_GET_FLAG(FLAGS_use_manifolds))
<< "--use_manifolds can only be used with --use_quaternions.";
ceres::examples::SolveProblem(CERES_GET_FLAG(FLAGS_input).c_str());
return 0;
}
+1 -1
View File
@@ -131,7 +131,7 @@ int main(int argc, char** argv) {
Problem problem;
// Configure the loss function.
LossFunction* loss = NULL;
LossFunction* loss = nullptr;
if (CERES_GET_FLAG(FLAGS_robust_threshold)) {
loss = new CauchyLoss(CERES_GET_FLAG(FLAGS_robust_threshold));
}
+1 -1
View File
@@ -145,7 +145,7 @@ int main(int argc, char** argv) {
problem.AddResidualBlock(
new AutoDiffCostFunction<ExponentialResidual, 1, 1, 1>(
new ExponentialResidual(data[2 * i], data[2 * i + 1])),
NULL,
nullptr,
&m,
&c);
}
+2 -2
View File
@@ -118,7 +118,7 @@ class QuadraticCostFunction : public ceres::SizedCostFunction<1, 1> {
double** jacobians) const {
const double x = parameters[0][0];
residuals[0] = sqrta_ * (x - b_);
if (jacobians != NULL && jacobians[0] != NULL) {
if (jacobians != nullptr && jacobians[0] != nullptr) {
jacobians[0][0] = sqrta_;
}
return true;
@@ -141,7 +141,7 @@ void CreateProblem(const FieldsOfExperts& foe,
ceres::CostFunction* cost_function = new QuadraticCostFunction(
coefficient, image.PixelFromLinearIndex(index));
problem->AddResidualBlock(
cost_function, NULL, solution->MutablePixelFromLinearIndex(index));
cost_function, nullptr, solution->MutablePixelFromLinearIndex(index));
}
// Create Ceres cost and loss functions for regularization. One is needed for
+6 -6
View File
@@ -302,16 +302,16 @@ class PointToLineSegmentContourCostFunction : public ceres::CostFunction {
residuals[0] = y_[0] - ((1.0 - u) * x[1 + i0][0] + u * x[1 + i1][0]);
residuals[1] = y_[1] - ((1.0 - u) * x[1 + i0][1] + u * x[1 + i1][1]);
if (jacobians == NULL) {
if (jacobians == nullptr) {
return true;
}
if (jacobians[0] != NULL) {
if (jacobians[0] != nullptr) {
jacobians[0][0] = x[1 + i0][0] - x[1 + i1][0];
jacobians[0][1] = x[1 + i0][1] - x[1 + i1][1];
}
for (int i = 0; i < num_segments_; ++i) {
if (jacobians[i + 1] != NULL) {
if (jacobians[i + 1] != nullptr) {
ceres::MatrixRef(jacobians[i + 1], 2, 2).setZero();
if (i == i0) {
jacobians[i + 1][0] = -(1.0 - u);
@@ -415,7 +415,7 @@ int main(int argc, char** argv) {
// For each data point add a residual which measures its distance to its
// corresponding position on the line segment contour.
std::vector<double*> parameter_blocks(1 + num_segments);
parameter_blocks[0] = NULL;
parameter_blocks[0] = nullptr;
for (int i = 0; i < num_segments; ++i) {
parameter_blocks[i + 1] = X.data() + 2 * i;
}
@@ -423,7 +423,7 @@ int main(int argc, char** argv) {
parameter_blocks[0] = &t[i];
problem.AddResidualBlock(
PointToLineSegmentContourCostFunction::Create(num_segments, kY.row(i)),
NULL,
nullptr,
parameter_blocks);
}
@@ -431,7 +431,7 @@ int main(int argc, char** argv) {
for (int i = 0; i < num_segments; ++i) {
problem.AddResidualBlock(
EuclideanDistanceFunctor::Create(sqrt(regularization_weight)),
NULL,
nullptr,
X.data() + 2 * i,
X.data() + 2 * ((i + 1) % num_segments));
}
+2 -2
View File
@@ -60,9 +60,9 @@ bool FieldsOfExpertsCost::Evaluate(double const* const* parameters,
residuals[0] += filter_[i] * parameters[i][0];
}
if (jacobians != NULL) {
if (jacobians != nullptr) {
for (int i = 0; i < num_variables; ++i) {
if (jacobians[i] != NULL) {
if (jacobians[i] != nullptr) {
jacobians[i][0] = filter_[i];
}
}
+4 -4
View File
@@ -64,14 +64,14 @@ class QuadraticCostFunction
// jacobians.
//
// Since the Evaluate function can be called with the jacobians
// pointer equal to NULL, the Evaluate function must check to see
// pointer equal to nullptr, the Evaluate function must check to see
// if jacobians need to be computed.
//
// For this simple problem it is overkill to check if jacobians[0]
// is NULL, but in general when writing more complex
// is nullptr, but in general when writing more complex
// CostFunctions, it is possible that Ceres may only demand the
// derivatives w.r.t. a subset of the parameter blocks.
if (jacobians != NULL && jacobians[0] != NULL) {
if (jacobians != nullptr && jacobians[0] != nullptr) {
jacobians[0][0] = -1;
}
@@ -92,7 +92,7 @@ int main(int argc, char** argv) {
// Set up the only cost function (also known as residual).
CostFunction* cost_function = new QuadraticCostFunction;
problem.AddResidualBlock(cost_function, NULL, &x);
problem.AddResidualBlock(cost_function, nullptr, &x);
// Run the solver!
Solver::Options options;
+1 -1
View File
@@ -64,7 +64,7 @@ int main(int argc, char** argv) {
// numeric differentiation to obtain the derivative (jacobian).
CostFunction* cost_function =
new NumericDiffCostFunction<CostFunctor, CENTRAL, 1, 1>(new CostFunctor);
problem.AddResidualBlock(cost_function, NULL, &x);
problem.AddResidualBlock(cost_function, nullptr, &x);
// Run the solver!
Solver::Options options;
+21 -20
View File
@@ -206,11 +206,11 @@ enum {
EuclideanCamera* CameraForImage(vector<EuclideanCamera>* all_cameras,
const int image) {
if (image < 0 || image >= all_cameras->size()) {
return NULL;
return nullptr;
}
EuclideanCamera* camera = &(*all_cameras)[image];
if (camera->image == -1) {
return NULL;
return nullptr;
}
return camera;
}
@@ -218,11 +218,11 @@ EuclideanCamera* CameraForImage(vector<EuclideanCamera>* all_cameras,
const EuclideanCamera* CameraForImage(
const vector<EuclideanCamera>& all_cameras, const int image) {
if (image < 0 || image >= all_cameras.size()) {
return NULL;
return nullptr;
}
const EuclideanCamera* camera = &all_cameras[image];
if (camera->image == -1) {
return NULL;
return nullptr;
}
return camera;
}
@@ -244,11 +244,11 @@ int MaxImage(const vector<Marker>& all_markers) {
EuclideanPoint* PointForTrack(vector<EuclideanPoint>* all_points,
const int track) {
if (track < 0 || track >= all_points->size()) {
return NULL;
return nullptr;
}
EuclideanPoint* point = &(*all_points)[track];
if (point->track == -1) {
return NULL;
return nullptr;
}
return point;
}
@@ -670,8 +670,8 @@ void EuclideanBundleCommonIntrinsics(const vector<Marker>& all_markers,
vector<Vec6> all_cameras_R_t =
PackCamerasRotationAndTranslation(all_markers, *all_cameras);
// Parameterization used to restrict camera motion for modal solvers.
ceres::SubsetParameterization* constant_transform_parameterization = NULL;
// Manifold used to restrict camera motion for modal solvers.
ceres::SubsetManifold* constant_transform_manifold = nullptr;
if (bundle_constraints & BUNDLE_NO_TRANSLATION) {
std::vector<int> constant_translation;
@@ -680,8 +680,8 @@ void EuclideanBundleCommonIntrinsics(const vector<Marker>& all_markers,
constant_translation.push_back(4);
constant_translation.push_back(5);
constant_transform_parameterization =
new ceres::SubsetParameterization(6, constant_translation);
constant_transform_manifold =
new ceres::SubsetManifold(6, constant_translation);
}
std::vector<OpenCVReprojectionError> errors;
@@ -696,7 +696,7 @@ void EuclideanBundleCommonIntrinsics(const vector<Marker>& all_markers,
const Marker& marker = all_markers[i];
EuclideanCamera* camera = CameraForImage(all_cameras, marker.image);
EuclideanPoint* point = PointForTrack(all_points, marker.track);
if (camera == NULL || point == NULL) {
if (camera == nullptr || point == nullptr) {
continue;
}
@@ -708,7 +708,7 @@ void EuclideanBundleCommonIntrinsics(const vector<Marker>& all_markers,
costFunctions.emplace_back(&errors.back(), ceres::DO_NOT_TAKE_OWNERSHIP);
problem.AddResidualBlock(&costFunctions.back(),
NULL,
nullptr,
camera_intrinsics,
current_camera_R_t,
&point->X(0));
@@ -720,8 +720,7 @@ void EuclideanBundleCommonIntrinsics(const vector<Marker>& all_markers,
}
if (bundle_constraints & BUNDLE_NO_TRANSLATION) {
problem.SetParameterization(current_camera_R_t,
constant_transform_parameterization);
problem.SetManifold(current_camera_R_t, constant_transform_manifold);
}
num_residuals++;
@@ -760,10 +759,9 @@ void EuclideanBundleCommonIntrinsics(const vector<Marker>& all_markers,
// Always set K3 constant, it's not used at the moment.
constant_intrinsics.push_back(OFFSET_K3);
ceres::SubsetParameterization* subset_parameterization =
new ceres::SubsetParameterization(8, constant_intrinsics);
problem.SetParameterization(camera_intrinsics, subset_parameterization);
ceres::SubsetManifold* subset_manifold =
new ceres::SubsetManifold(8, constant_intrinsics);
problem.SetManifold(camera_intrinsics, subset_manifold);
}
// Configure the solver.
@@ -804,8 +802,11 @@ int main(int argc, char** argv) {
bool is_image_space;
vector<Marker> all_markers;
if (!ReadProblemFromFile(CERES_GET_FLAG(FLAGS_input), camera_intrinsics,
&all_cameras, &all_points, &is_image_space,
if (!ReadProblemFromFile(CERES_GET_FLAG(FLAGS_input),
camera_intrinsics,
&all_cameras,
&all_points,
&is_image_space,
&all_markers)) {
LOG(ERROR) << "Error reading problem file";
return EXIT_FAILURE;
+1 -1
View File
@@ -335,7 +335,7 @@ bool EstimateHomography2DFromCorrespondences(
4, // num_residuals
9>(
homography_symmetric_geometric_cost_function),
NULL,
nullptr,
H->data());
}
+14 -8
View File
@@ -95,20 +95,26 @@ static void SetNumericDiffOptions(ceres::NumericDiffOptions* options) {
ceres::NumericDiffOptions options; \
SetNumericDiffOptions(&options); \
if (CERES_GET_FLAG(FLAGS_numeric_diff_method) == "central") { \
return new NumericDiffCostFunction<name, ceres::CENTRAL, \
num_residuals, num_parameters>( \
return new NumericDiffCostFunction<name, \
ceres::CENTRAL, \
num_residuals, \
num_parameters>( \
new name, ceres::TAKE_OWNERSHIP, num_residuals, options); \
} else if (CERES_GET_FLAG(FLAGS_numeric_diff_method) == "forward") { \
return new NumericDiffCostFunction<name, ceres::FORWARD, \
num_residuals, num_parameters>( \
return new NumericDiffCostFunction<name, \
ceres::FORWARD, \
num_residuals, \
num_parameters>( \
new name, ceres::TAKE_OWNERSHIP, num_residuals, options); \
} else if (CERES_GET_FLAG(FLAGS_numeric_diff_method) == "ridders") { \
return new NumericDiffCostFunction<name, ceres::RIDDERS, \
num_residuals, num_parameters>( \
return new NumericDiffCostFunction<name, \
ceres::RIDDERS, \
num_residuals, \
num_parameters>( \
new name, ceres::TAKE_OWNERSHIP, num_residuals, options); \
} else { \
LOG(ERROR) << "Invalid numeric diff method specified"; \
return NULL; \
return nullptr; \
} \
} else { \
return new AutoDiffCostFunction<name, num_residuals, num_parameters>( \
@@ -543,7 +549,7 @@ bool Solve(bool is_constrained, int trial) {
}
Problem problem;
problem.AddResidualBlock(TestProblem::Create(), NULL, x);
problem.AddResidualBlock(TestProblem::Create(), nullptr, x);
double optimal_cost = TestProblem::unconstrained_optimal_cost;
if (is_constrained) {
+3 -2
View File
@@ -523,7 +523,7 @@ CostFunction* CreateCostFunction(const Matrix& predictor,
const Matrix& response,
const int num_observations) {
Model* model = new Model(predictor.data(), response.data(), num_observations);
ceres::CostFunction* cost_function = NULL;
ceres::CostFunction* cost_function = nullptr;
if (CERES_GET_FLAG(FLAGS_use_numeric_diff)) {
ceres::NumericDiffOptions options;
SetNumericDiffOptions(&options);
@@ -603,7 +603,8 @@ int RegressionDriver(const string& filename) {
if (!CERES_GET_FLAG(FLAGS_use_tiny_solver)) {
ceres::Problem problem;
problem.AddResidualBlock(cost_function, NULL, initial_parameters.data());
problem.AddResidualBlock(
cost_function, nullptr, initial_parameters.data());
ceres::Solver::Summary summary;
ceres::Solver::Options options;
SetMinimizerOptions(&options);
+7 -6
View File
@@ -110,17 +110,18 @@ int main(int argc, char** argv) {
// wrapper to get the derivatives automatically. The parameters, x1 through
// x4, are modified in place.
problem.AddResidualBlock(
new AutoDiffCostFunction<F1, 1, 1, 1>(new F1), NULL, &x1, &x2);
new AutoDiffCostFunction<F1, 1, 1, 1>(new F1), nullptr, &x1, &x2);
problem.AddResidualBlock(
new AutoDiffCostFunction<F2, 1, 1, 1>(new F2), NULL, &x3, &x4);
new AutoDiffCostFunction<F2, 1, 1, 1>(new F2), nullptr, &x3, &x4);
problem.AddResidualBlock(
new AutoDiffCostFunction<F3, 1, 1, 1>(new F3), NULL, &x2, &x3);
new AutoDiffCostFunction<F3, 1, 1, 1>(new F3), nullptr, &x2, &x3);
problem.AddResidualBlock(
new AutoDiffCostFunction<F4, 1, 1, 1>(new F4), NULL, &x1, &x4);
new AutoDiffCostFunction<F4, 1, 1, 1>(new F4), nullptr, &x1, &x4);
Solver::Options options;
LOG_IF(FATAL, !ceres::StringToMinimizerType(CERES_GET_FLAG(FLAGS_minimizer),
&options.minimizer_type))
LOG_IF(FATAL,
!ceres::StringToMinimizerType(CERES_GET_FLAG(FLAGS_minimizer),
&options.minimizer_type))
<< "Invalid minimizer: " << CERES_GET_FLAG(FLAGS_minimizer)
<< ", valid options are: trust_region and line_search.";
+2 -2
View File
@@ -315,12 +315,12 @@ int main(int argc, char** argv) {
RangeConstraint::RangeCostFunction* range_cost_function =
RangeConstraint::Create(
i, range_readings[i], &odometry_values, &parameter_blocks);
problem.AddResidualBlock(range_cost_function, NULL, parameter_blocks);
problem.AddResidualBlock(range_cost_function, nullptr, parameter_blocks);
// Create and add an AutoDiffCostFunction for the OdometryConstraint for
// pose i.
problem.AddResidualBlock(OdometryConstraint::Create(odometry_values[i]),
NULL,
nullptr,
&(odometry_values[i]));
}
+2 -2
View File
@@ -66,7 +66,7 @@ class BALProblem {
bool LoadFile(const char* filename) {
FILE* fptr = fopen(filename, "r");
if (fptr == NULL) {
if (fptr == nullptr) {
return false;
};
@@ -198,7 +198,7 @@ int main(int argc, char** argv) {
ceres::CostFunction* cost_function = SnavelyReprojectionError::Create(
observations[2 * i + 0], observations[2 * i + 1]);
problem.AddResidualBlock(cost_function,
NULL /* squared loss */,
nullptr /* squared loss */,
bal_problem.mutable_camera_for_observation(i),
bal_problem.mutable_point_for_observation(i));
}
+1 -1
View File
@@ -30,7 +30,7 @@
if (GFLAGS)
add_executable(pose_graph_2d
angle_local_parameterization.h
angle_manifold.h
normalize_angle.h
pose_graph_2d.cc
pose_graph_2d_error_term.h
@@ -1,5 +1,5 @@
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2016 Google Inc. All rights reserved.
// Copyright 2022 Google Inc. All rights reserved.
// http://ceres-solver.org/
//
// Redistribution and use in source and binary forms, with or without
@@ -27,38 +27,44 @@
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: vitus@google.com (Michael Vitus)
// sameeragarwal@google.com (Sameer Agarwal)
#ifndef CERES_EXAMPLES_POSE_GRAPH_2D_ANGLE_LOCAL_PARAMETERIZATION_H_
#define CERES_EXAMPLES_POSE_GRAPH_2D_ANGLE_LOCAL_PARAMETERIZATION_H_
#ifndef CERES_EXAMPLES_POSE_GRAPH_2D_ANGLE_MANIFOLD_H_
#define CERES_EXAMPLES_POSE_GRAPH_2D_ANGLE_MANIFOLD_H_
#include "ceres/local_parameterization.h"
#include "ceres/autodiff_manifold.h"
#include "normalize_angle.h"
namespace ceres {
namespace examples {
// Defines a local parameterization for updating the angle to be constrained in
// [-pi to pi).
class AngleLocalParameterization {
// Defines a manifold for updating the angle to be constrained in [-pi to pi).
class AngleManifold {
public:
template <typename T>
bool operator()(const T* theta_radians,
const T* delta_theta_radians,
T* theta_radians_plus_delta) const {
*theta_radians_plus_delta =
NormalizeAngle(*theta_radians + *delta_theta_radians);
bool Plus(const T* x_radians,
const T* delta_radians,
T* x_plus_delta_radians) const {
*x_plus_delta_radians = NormalizeAngle(*x_radians + *delta_radians);
return true;
}
template <typename T>
bool Minus(const T* y_radians,
const T* x_radians,
T* y_minus_x_radians) const {
*y_minus_x_radians =
NormalizeAngle(*y_radians) - NormalizeAngle(*x_radians);
return true;
}
static ceres::LocalParameterization* Create() {
return (new ceres::AutoDiffLocalParameterization<AngleLocalParameterization,
1,
1>);
static ceres::Manifold* Create() {
return new ceres::AutoDiffManifold<AngleManifold, 1, 1>;
}
};
} // namespace examples
} // namespace ceres
#endif // CERES_EXAMPLES_POSE_GRAPH_2D_ANGLE_LOCAL_PARAMETERIZATION_H_
#endif // CERES_EXAMPLES_POSE_GRAPH_2D_ANGLE_MANIFOLD_H_
+8 -11
View File
@@ -39,7 +39,7 @@
#include <string>
#include <vector>
#include "angle_local_parameterization.h"
#include "angle_manifold.h"
#include "ceres/ceres.h"
#include "common/read_g2o.h"
#include "gflags/gflags.h"
@@ -58,16 +58,15 @@ namespace {
void BuildOptimizationProblem(const std::vector<Constraint2d>& constraints,
std::map<int, Pose2d>* poses,
ceres::Problem* problem) {
CHECK(poses != NULL);
CHECK(problem != NULL);
CHECK(poses != nullptr);
CHECK(problem != nullptr);
if (constraints.empty()) {
LOG(INFO) << "No constraints, no problem to optimize.";
return;
}
ceres::LossFunction* loss_function = NULL;
ceres::LocalParameterization* angle_local_parameterization =
AngleLocalParameterization::Create();
ceres::LossFunction* loss_function = nullptr;
ceres::Manifold* angle_manifold = AngleManifold::Create();
for (std::vector<Constraint2d>::const_iterator constraints_iter =
constraints.begin();
@@ -98,10 +97,8 @@ void BuildOptimizationProblem(const std::vector<Constraint2d>& constraints,
&pose_end_iter->second.y,
&pose_end_iter->second.yaw_radians);
problem->SetParameterization(&pose_begin_iter->second.yaw_radians,
angle_local_parameterization);
problem->SetParameterization(&pose_end_iter->second.yaw_radians,
angle_local_parameterization);
problem->SetManifold(&pose_begin_iter->second.yaw_radians, angle_manifold);
problem->SetManifold(&pose_end_iter->second.yaw_radians, angle_manifold);
}
// The pose graph optimization problem has three DOFs that are not fully
@@ -120,7 +117,7 @@ void BuildOptimizationProblem(const std::vector<Constraint2d>& constraints,
// Returns true if the solve was successful.
bool SolveOptimizationProblem(ceres::Problem* problem) {
CHECK(problem != NULL);
CHECK(problem != nullptr);
ceres::Solver::Options options;
options.max_num_iterations = 100;
+9 -10
View File
@@ -50,16 +50,15 @@ namespace {
void BuildOptimizationProblem(const VectorOfConstraints& constraints,
MapOfPoses* poses,
ceres::Problem* problem) {
CHECK(poses != NULL);
CHECK(problem != NULL);
CHECK(poses != nullptr);
CHECK(problem != nullptr);
if (constraints.empty()) {
LOG(INFO) << "No constraints, no problem to optimize.";
return;
}
ceres::LossFunction* loss_function = NULL;
ceres::LocalParameterization* quaternion_local_parameterization =
new EigenQuaternionParameterization;
ceres::LossFunction* loss_function = nullptr;
ceres::Manifold* quaternion_manifold = new EigenQuaternionManifold;
for (VectorOfConstraints::const_iterator constraints_iter =
constraints.begin();
@@ -87,10 +86,10 @@ void BuildOptimizationProblem(const VectorOfConstraints& constraints,
pose_end_iter->second.p.data(),
pose_end_iter->second.q.coeffs().data());
problem->SetParameterization(pose_begin_iter->second.q.coeffs().data(),
quaternion_local_parameterization);
problem->SetParameterization(pose_end_iter->second.q.coeffs().data(),
quaternion_local_parameterization);
problem->SetManifold(pose_begin_iter->second.q.coeffs().data(),
quaternion_manifold);
problem->SetManifold(pose_end_iter->second.q.coeffs().data(),
quaternion_manifold);
}
// The pose graph optimization problem has six DOFs that are not fully
@@ -108,7 +107,7 @@ void BuildOptimizationProblem(const VectorOfConstraints& constraints,
// Returns true if the solve was successful.
bool SolveOptimizationProblem(ceres::Problem* problem) {
CHECK(problem != NULL);
CHECK(problem != nullptr);
ceres::Solver::Options options;
options.max_num_iterations = 200;
+1 -1
View File
@@ -123,7 +123,7 @@ struct SnavelyReprojectionErrorWithQuaternions {
// We use QuaternionRotatePoint as it does not assume that the
// quaternion is normalized, since one of the ways to run the
// bundle adjuster is to let Ceres optimize all 4 quaternion
// parameters without a local parameterization.
// parameters without using a Quaternion manifold.
T p[3];
QuaternionRotatePoint(camera, point, p);
+1
View File
@@ -57,6 +57,7 @@
#include "ceres/jet.h"
#include "ceres/local_parameterization.h"
#include "ceres/loss_function.h"
#include "ceres/manifold.h"
#include "ceres/numeric_diff_cost_function.h"
#include "ceres/numeric_diff_first_order_function.h"
#include "ceres/numeric_diff_options.h"
@@ -429,7 +429,7 @@ TEST(GradientCheckingProblemImpl, ProblemDimensionsMatch) {
problem_impl.AddParameterBlock(y, 4);
problem_impl.SetParameterBlockConstant(y);
problem_impl.AddParameterBlock(z, 5);
problem_impl.AddParameterBlock(w, 4, new Quaternion);
problem_impl.AddParameterBlock(w, 4, new QuaternionManifold);
// clang-format off
problem_impl.AddResidualBlock(new UnaryCostFunction(2, 3),
nullptr, x);