1 #ifndef CALICO_SENSORS_CAMERA_COST_FUNCTOR_H_
2 #define CALICO_SENSORS_CAMERA_COST_FUNCTOR_H_
9 #include "calico/sensors/camera_models.h"
10 #include "calico/trajectory.h"
11 #include "ceres/cost_function.h"
16 enum class CameraParameterIndices : int {
20 kExtrinsicsRotationIndex = 1,
21 kExtrinsicsTranslationIndex = 2,
31 kModelRotationIndex = 5,
32 kModelTranslationIndex = 6,
35 kSensorRigPoseSplineControlPointsIndex = 7,
42 static constexpr
int kCameraResidualSize = 2;
44 const Eigen::Vector2d& pixel,
double sigma,
49 static ceres::CostFunction* CreateCostFunction(
50 const Eigen::Vector2d& pixel,
double sigma,
52 Pose3d& extrinsics,
double& latency, Eigen::Vector3d& t_model_point,
54 double stamp, std::vector<double*>& parameters);
77 bool operator()(T
const*
const* parameters, T* residual) {
79 const T* intrinsics_ptr =
static_cast<const T*
>(
80 &(parameters[
static_cast<int>(CameraParameterIndices::kIntrinsicsIndex)]
82 const int parameter_size = camera_model_->NumberOfParameters();
83 const Eigen::VectorX<T> intrinsics =
84 Eigen::Map<const Eigen::VectorX<T>>(intrinsics_ptr, parameter_size);
86 const Eigen::Map<const Eigen::Quaternion<T>> q_sensorrig_camera(
87 &(parameters[
static_cast<int>(
88 CameraParameterIndices::kExtrinsicsRotationIndex)][0]));
89 const Eigen::Map<const Eigen::Vector3<T>> t_sensorrig_camera(
90 &(parameters[
static_cast<int>(
91 CameraParameterIndices::kExtrinsicsTranslationIndex)][0]));
94 parameters[
static_cast<int>(CameraParameterIndices::kLatencyIndex)][0];
96 const Eigen::Map<const Eigen::Vector3<T>> t_model_point(
97 &(parameters[
static_cast<int>(CameraParameterIndices::kModelPointIndex)]
99 const Eigen::Map<const Eigen::Quaternion<T>> q_world_model(
100 &(parameters[
static_cast<int>(
101 CameraParameterIndices::kModelRotationIndex)][0]));
102 const Eigen::Map<const Eigen::Vector3<T>> t_world_model(
103 &(parameters[
static_cast<int>(
104 CameraParameterIndices::kModelTranslationIndex)][0]));
106 const int num_rotation_control_points =
107 rotation_trajectory_evaluation_params_.num_control_points;
108 Eigen::MatrixX<T> rotation_control_points(num_rotation_control_points, 3);
109 for (
int i = 0; i < num_rotation_control_points; ++i) {
110 rotation_control_points.row(i) = Eigen::Map<const Eigen::Vector3<T>>(
111 &(parameters[
static_cast<int>(
112 CameraParameterIndices::
113 kSensorRigPoseSplineControlPointsIndex) +
116 const int num_position_control_points =
117 position_trajectory_evaluation_params_.num_control_points;
118 Eigen::MatrixX<T> position_control_points(num_position_control_points, 3);
119 for (
int i = 0; i < num_position_control_points; ++i) {
120 position_control_points.row(i) = Eigen::Map<const Eigen::Vector3<T>>(
121 &(parameters[
static_cast<int>(
122 CameraParameterIndices::
123 kSensorRigPoseSplineControlPointsIndex) +
124 i + num_rotation_control_points][0]));
127 const Eigen::MatrixX<T> rotation_basis_matrix =
128 rotation_trajectory_evaluation_params_.basis_matrix.template cast<T>();
129 const T rotation_knot0 =
130 static_cast<T
>(rotation_trajectory_evaluation_params_.knot0);
131 const T rotation_knot1 =
132 static_cast<T
>(rotation_trajectory_evaluation_params_.knot1);
133 const T rotation_stamp =
134 static_cast<T
>(rotation_trajectory_evaluation_params_.stamp) - latency;
136 const Eigen::MatrixX<T> position_basis_matrix =
137 position_trajectory_evaluation_params_.basis_matrix.template cast<T>();
138 const T position_knot0 =
139 static_cast<T
>(position_trajectory_evaluation_params_.knot0);
140 const T position_knot1 =
141 static_cast<T
>(position_trajectory_evaluation_params_.knot1);
142 const T position_stamp =
143 static_cast<T
>(position_trajectory_evaluation_params_.stamp) - latency;
146 rotation_control_points, rotation_knot0, rotation_knot1,
147 rotation_basis_matrix, rotation_stamp, 0);
148 T q_sensorrig_world_array[4];
149 ceres::AngleAxisToQuaternion(phi_sensorrig_world.data(),
150 q_sensorrig_world_array);
151 const Eigen::Quaternion<T> q_sensorrig_world(
152 q_sensorrig_world_array[0], q_sensorrig_world_array[1],
153 q_sensorrig_world_array[2], q_sensorrig_world_array[3]);
155 position_control_points, position_knot0, position_knot1,
156 position_basis_matrix, position_stamp, 0);
159 const Eigen::Quaternion<T> q_camera_model =
160 q_sensorrig_camera.inverse() * q_sensorrig_world * q_world_model;
161 const Eigen::Vector3<T> t_world_camera =
162 t_world_sensorrig + q_sensorrig_world.inverse() * t_sensorrig_camera;
163 const Eigen::Vector3<T> t_model_camera =
164 q_world_model.inverse() * (t_world_camera - t_world_model);
165 const Eigen::Vector3<T> t_camera_point =
166 q_camera_model * (t_model_point - t_model_camera);
167 const absl::StatusOr<Eigen::Vector2<T>> projection =
168 camera_model_->ProjectPoint(intrinsics, t_camera_point);
173 Eigen::Map<Eigen::Vector2<T>> error(residual);
174 if (projection.ok()) {
175 const Eigen::Vector2<T> pixel = pixel_.template cast<T>();
176 error = (pixel - *projection) *
static_cast<T
>(information_);
179 std::cerr <<
"projection failed inside cost functor: "
180 << projection.status().message()
181 <<
" stamp=" << rotation_trajectory_evaluation_params_.stamp
182 <<
" t_camera_point=" << t_camera_point.transpose() << std::endl;
187 Eigen::Vector2d pixel_;
189 std::unique_ptr<CameraModel> camera_model_;
Definition: trajectory.h:25
Definition: camera_cost_functor.h:40
Sensors namespace.
Definition: accelerometer.cpp:8
CameraIntrinsicsModel
Camera model types.
Definition: camera_models.h:16
Definition: trajectory.h:14