19 #ifndef FACTOR_ADDERS_LOC_FACTOR_ADDER_H_
20 #define FACTOR_ADDERS_LOC_FACTOR_ADDER_H_
36 template <
typename PoseNodeAdderType>
51 int AddFactorsForSingleMeasurement(
53 gtsam::NonlinearFactorGraph& factors)
final;
60 gtsam::NonlinearFactorGraph& factors);
63 int AddLocProjectionFactor(
65 gtsam::NonlinearFactorGraph& factors);
69 gtsam::NonlinearFactorGraph& factors);
73 template <
class Archive>
74 void serialize(Archive& ar,
const unsigned int file_version) {
75 ar& BOOST_SERIALIZATION_BASE_OBJECT_NVP(
Base);
76 ar& BOOST_SERIALIZATION_NVP(node_adder_);
77 ar& BOOST_SERIALIZATION_NVP(params_);
78 ar& BOOST_SERIALIZATION_NVP(num_landmarks_averager_);
79 ar& BOOST_SERIALIZATION_NVP(pose_prior_noise_sigmas_);
82 std::shared_ptr<PoseNodeAdderType> node_adder_;
85 gtsam::Vector6 pose_prior_noise_sigmas_;
89 template <
typename PoseNodeAdderType>
91 std::shared_ptr<PoseNodeAdderType> node_adder)
92 :
Base(params), params_(params), node_adder_(node_adder) {
99 template <
typename PoseNodeAdderType>
102 gtsam::NonlinearFactorGraph& factors) {
104 LogDebug(
"AddFactorsForSingleMeasurement: Empty measurement.");
109 params_.min_num_matches_per_measurement) {
110 LogDebug(
"AddFactorsForSingleMeasurement: Not enough matches in projection measurement.");
115 num_landmarks_averager_.Update(num_landmarks);
116 int num_loc_projection_factors = 0;
117 int num_loc_pose_factors = 0;
118 if (params_.add_projection_factors) {
119 num_loc_projection_factors = AddLocProjectionFactor(matched_projections_measurement, factors);
122 if (num_loc_projection_factors == 0 && params_.add_prior_if_projection_factors_fail) {
123 num_loc_pose_factors = AddLocPoseFactor(matched_projections_measurement, factors);
127 if (params_.add_pose_priors && num_loc_pose_factors == 0) {
128 num_loc_pose_factors = AddLocPoseFactor(matched_projections_measurement, factors);
130 return num_loc_pose_factors + num_loc_projection_factors;
133 template <
typename PoseNodeAdderType>
134 bool LocFactorAdder<PoseNodeAdderType>::CanAddFactor(
136 return node_adder_->CanAddNode(measurement.
timestamp);
139 template <
typename PoseNodeAdderType>
140 int LocFactorAdder<PoseNodeAdderType>::AddLocProjectionFactor(
142 gtsam::NonlinearFactorGraph& factors) {
143 double noise_scale = params_.projection_noise_scale;
144 if (params_.scale_projection_noise_with_num_landmarks) {
146 noise_scale *= std::pow((num_landmarks_averager_.average() /
static_cast<double>(num_landmarks)), 2);
148 const auto pose_key = AddPoseNode(matched_projections_measurement.
timestamp, factors);
150 LogError(
"AddLocProjectionFactors: Failed to get pose key.");
155 LogError(
"AddLocProjectionFactors: Failed to get world_T_body at timestamp "
156 << matched_projections_measurement.
timestamp <<
".");
160 int num_loc_projection_factors = 0;
161 for (
const auto& matched_projection : matched_projections_measurement.
matched_projections) {
162 gtsam::SharedNoiseModel noise;
164 if (params_.scale_projection_noise_with_landmark_distance) {
165 const Eigen::Vector3d& world_t_landmark = matched_projection.map_point;
168 const gtsam::Point3 nav_cam_t_landmark = nav_cam_T_world * world_t_landmark;
170 noise = gtsam::SharedIsotropic(
171 gtsam::noiseModel::Isotropic::Sigma(2, params_.projection_noise_scale * 1.0 / nav_cam_t_landmark.z()));
174 gtsam::SharedIsotropic(gtsam::noiseModel::Isotropic::Sigma(2, noise_scale * params_.cam_noise->sigma())),
179 params_.cam_intrinsics, params_.body_T_cam));
182 const auto error = (loc_projection_factor->evaluateError(*world_T_body)).norm();
183 if (
error > params_.max_valid_projection_error)
continue;
184 const auto cheirality_error = loc_projection_factor->cheiralityError(*world_T_body);
185 if (cheirality_error)
continue;
186 factors.push_back(loc_projection_factor);
187 ++num_loc_projection_factors;
188 if (num_loc_projection_factors >= params_.max_num_projection_factors)
break;
191 LogDebug(
"AddFactorsForSingleMeasurement: Added " << num_loc_projection_factors
192 <<
" loc projection factors at timestamp "
193 << matched_projections_measurement.
timestamp <<
".");
194 return num_loc_projection_factors;
197 template <
typename PoseNodeAdderType>
198 int LocFactorAdder<PoseNodeAdderType>::AddLocPoseFactor(
200 gtsam::NonlinearFactorGraph& factors) {
201 double noise_scale = params_.pose_noise_scale;
202 if (params_.scale_pose_noise_with_num_landmarks) {
204 noise_scale *= std::pow((num_landmarks_averager_.average() /
static_cast<double>(num_landmarks)), 2);
206 const auto pose_key = AddPoseNode(matched_projections_measurement.
timestamp, factors);
208 LogError(
"AddLocProjectionFactors: Failed to get pose key.");
213 gtsam::noiseModel::Diagonal::Sigmas(Eigen::Ref<const Eigen::VectorXd>(noise_scale * pose_prior_noise_sigmas_)),
217 *pose_key, matched_projections_measurement.
global_T_cam * params_.body_T_cam.inverse(), pose_noise));
218 factors.push_back(pose_prior_factor);
219 LogDebug(
"AddLocPoseFactor: Added loc pose prior factor at timestamp " << matched_projections_measurement.
timestamp
224 template <
typename PoseNodeAdderType>
226 gtsam::NonlinearFactorGraph& factors) {
227 if (!node_adder_->AddNode(timestamp, factors)) {
228 LogError(
"AddLocPoseFactor: Failed to add node for timestamp " << timestamp <<
".");
231 const auto keys = node_adder_->Keys(timestamp);
233 LogError(
"AddLocPoseFactor: Failed to get keys for timestamp " << timestamp <<
".");
238 const auto& pose_key = keys[0];
243 #endif // FACTOR_ADDERS_LOC_FACTOR_ADDER_H_