Calico
A visual-inertial calibration library designed for rapid problem construction and debugging.
multi_camera.h
1 #ifndef CALICO_SENSORS_MULTI_CAMERA_H_
2 #define CALICO_SENSORS_MULTI_CAMERA_H_
3 
4 #include <memory>
5 #include <string>
6 #include <vector>
7 
8 #include "Eigen/Dense"
9 #include "absl/container/flat_hash_map.h"
10 #include "absl/container/flat_hash_set.h"
11 #include "absl/status/status.h"
12 #include "absl/strings/string_view.h"
13 #include "calico/sensors/camera.h"
14 #include "calico/sensors/camera_models.h"
15 #include "calico/sensors/sensor_base.h"
16 #include "calico/trajectory.h"
17 #include "calico/typedefs.h"
18 #include "ceres/problem.h"
19 
20 namespace calico::sensors {
21 
24 class MultiCamera : public Sensor {
25  public:
26  MultiCamera() = delete; // Require instantiation with imager names.
27  explicit MultiCamera(const absl::flat_hash_set<std::string>& imagers)
28  : imagers_(imagers) {
29  for (const auto& imager : imagers_) {
30  imager_to_intrinsics_enabled_[imager] = false;
31  imager_to_extrinsics_enabled_[imager] = false;
32  imager_to_latency_enabled_[imager] = false;
33  imager_to_camera_model_[imager] = nullptr;
34  imager_to_pose_sensor_from_imager_[imager] = Pose3d();
35  imager_to_intrinsics_[imager] = Eigen::VectorXd(0);
36  imager_to_latency_[imager] = 0.0;
37  imager_to_id_to_measurement_.insert({imager, {}});
38  imager_to_id_to_residual_.insert({imager, {}});
39  imager_to_id_to_residual_id_.insert({imager, {}});
40  imager_to_outlier_ids_.insert({imager, {}});
41  }
42  }
43  MultiCamera(const MultiCamera&) = delete;
44  MultiCamera& operator=(const MultiCamera&) = delete;
45  ~MultiCamera() = default;
46 
47  // /// Top-level sensor module name.
48  void SetName(const std::string& sensor_name) { sensor_name_ = sensor_name; }
49  const std::string& GetName() const { return sensor_name_; }
50 
52  absl::Status SetModel(const std::string& imager,
53  CameraIntrinsicsModel camera_model);
54 
56  absl::StatusOr<CameraIntrinsicsModel> GetModel(
57  const std::string& imager) const;
58 
62  void SetSensorExtrinsics(const Pose3d& pose_sensorrig_from_sensor) {
63  pose_sensorrig_from_sensor_ = pose_sensorrig_from_sensor;
64  }
65  const Pose3d& GetSensorExtrinsics() const {
66  return pose_sensorrig_from_sensor_;
67  }
68 
72  absl::Status SetImagerExtrinsics(const std::string& imager,
73  const Pose3d& pose_sensor_from_imager);
74  absl::StatusOr<Pose3d> GetImagerExtrinsics(const std::string& imager) const;
75 
76  absl::Status SetIntrinsics(const std::string& imager,
77  const Eigen::VectorXd& intrinsics);
78  absl::StatusOr<Eigen::VectorXd> GetIntrinsics(
79  const std::string& imager) const {
80  if (!imagers_.contains(imager)) {
81  return absl::InvalidArgumentError(
82  absl::StrCat("Imager ", imager, " not found in multi-camera set."));
83  }
84  return imager_to_intrinsics_.at(imager);
85  }
86 
87  absl::Status SetLatency(const std::string& imager, double latency) {
88  imager_to_latency_[imager] = latency;
89  return absl::OkStatus();
90  }
91  absl::StatusOr<double> GetLatency(const std::string& imager) const {
92  if (!imagers_.contains(imager)) {
93  return absl::InvalidArgumentError(
94  absl::StrCat("Imager ", imager, " not found in MultiCamera."));
95  }
96  return imager_to_latency_.at(imager);
97  }
98 
99  void EnableExtrinsicsEstimation(bool enable) {
100  sensor_extrinsics_enabled_ = enable;
101  }
102  absl::Status EnableExtrinsicsEstimation(const std::string& imager,
103  bool enable) {
104  if (!imagers_.contains(imager)) {
105  return absl::InvalidArgumentError(
106  absl::StrCat("Imager ", imager, " not found in MultiCamera."));
107  }
108  imager_to_extrinsics_enabled_[imager] = enable;
109  return absl::OkStatus();
110  }
111 
112  absl::Status EnableIntrinsicsEstimation(const std::string& imager,
113  bool enable) {
114  if (!imagers_.contains(imager)) {
115  return absl::InvalidArgumentError(
116  absl::StrCat("Imager ", imager, " not found in MultiCamera."));
117  }
118  imager_to_intrinsics_enabled_[imager] = enable;
119  return absl::OkStatus();
120  }
121  absl::Status EnableLatencyEstimation(const std::string& imager, bool enable) {
122  if (!imagers_.contains(imager)) {
123  return absl::InvalidArgumentError(
124  absl::StrCat("Imager ", imager, " not found in MultiCamera."));
125  }
126  imager_to_latency_enabled_[imager] = enable;
127  return absl::OkStatus();
128  }
129  void SetLossFunction(utils::LossFunctionType loss, double scale) final {
130  loss_function_ = loss;
131  loss_scale_ = scale;
132  }
133  absl::StatusOr<int> AddParametersToProblem(ceres::Problem& problem) final;
134  absl::StatusOr<int> AddResidualsToProblem(ceres::Problem& problem,
135  Trajectory& sensorrig_trajectory,
136  WorldModel& world_model) final;
137  absl::Status SetMeasurementNoise(double sigma) final {
138  if (sigma > 0) {
139  sigma_ = sigma;
140  return absl::OkStatus();
141  }
142  return absl::InvalidArgumentError(
143  absl::StrCat("Cannot set ", GetName(), " measurement noise to ", sigma,
144  ". Measurement noise must be positive."));
145  }
146  absl::Status UpdateResiduals(ceres::Problem& problem) final;
147  void ClearResidualInfo() final {
148  for (auto& [_, id_to_residual_] : imager_to_id_to_residual_) {
149  id_to_residual_.clear();
150  }
151  for (auto& [_, id_to_residual_id_] : imager_to_id_to_residual_id_) {
152  id_to_residual_id_.clear();
153  }
154  }
155 
167  absl::StatusOr<
168  absl::flat_hash_map<std::string, std::vector<CameraMeasurement>>>
169  Project(const std::vector<double>& interp_times,
170  const Trajectory& sensorrig_trajectory,
171  const WorldModel& world_model) const;
172 
175  absl::Status AddMeasurement(const std::string& imager,
176  const CameraMeasurement& measurement);
177 
184  absl::Status AddMeasurements(
185  const std::string& imager,
186  const std::vector<CameraMeasurement>& measurements);
187 
190  const absl::flat_hash_map<
191  std::string, absl::flat_hash_map<CameraObservationId, CameraMeasurement>>&
193  return imager_to_id_to_measurement_;
194  }
195 
197 
203  absl::StatusOr<absl::flat_hash_map<
204  std::string, std::vector<std::pair<CameraMeasurement, Eigen::Vector2d>>>>
206 
207  // /// Tag a single measurement as an outlier by its measurement ID.
208 
209  // /// Camera class keeps track of an outliers list internally. If passed a
210  // /// measurement ID that does not correspond with any measurement tracked by
211  // /// this camera, an InvalidArgument status is returned.
212  // absl::Status MarkOutlierById(const CameraObservationId& id);
213 
214  // /// Tag multiple measurements as outliers by measurement ID.
215 
216  // /// Camera class keeps track of an outliers list internally. If passed a
217  // /// measurement ID that does not correspond with any measurement tracked by
218  // /// this camera, an InvalidArgument status is returned.
219  // absl::Status MarkOutliersById(const std::vector<CameraObservationId>& ids);
220 
221  // /// Clear outliers list.
222  // void ClearOutliersList();
223 
224  // /// Clear all measurements.
225 
227  void ClearMeasurements();
228 
230  int NumberOfMeasurements(const std::string& imager) const;
231 
232  private:
233  std::string sensor_name_;
234  const absl::flat_hash_set<std::string> imagers_;
235 
236  Pose3d pose_sensorrig_from_sensor_;
237  bool sensor_extrinsics_enabled_ = false;
238  absl::flat_hash_map<std::string, bool> imager_to_intrinsics_enabled_;
239  absl::flat_hash_map<std::string, bool> imager_to_extrinsics_enabled_;
240  absl::flat_hash_map<std::string, bool> imager_to_latency_enabled_;
241  absl::flat_hash_map<std::string, std::unique_ptr<CameraModel>>
242  imager_to_camera_model_;
243  absl::flat_hash_map<std::string, Pose3d> imager_to_pose_sensor_from_imager_;
244  absl::flat_hash_map<std::string, Eigen::VectorXd> imager_to_intrinsics_;
245  absl::flat_hash_map<std::string, double> imager_to_latency_;
246  double sigma_ = 1.0;
247  utils::LossFunctionType loss_function_;
248  double loss_scale_ = 1.0;
249  absl::flat_hash_map<
250  std::string, absl::flat_hash_map<CameraObservationId, CameraMeasurement>>
251  imager_to_id_to_measurement_;
252  absl::flat_hash_map<std::string,
253  absl::flat_hash_map<CameraObservationId, Eigen::Vector2d>>
254  imager_to_id_to_residual_;
255  absl::flat_hash_map<std::string, absl::flat_hash_map<CameraObservationId,
256  ceres::ResidualBlockId>>
257  imager_to_id_to_residual_id_;
258  absl::flat_hash_map<std::string, absl::flat_hash_set<CameraObservationId>>
259  imager_to_outlier_ids_;
260 };
261 
262 } // namespace calico::sensors
263 
264 #endif // CALICO_SENSORS_CAMERA_H_
Definition: trajectory.h:25
Definition: world_model.h:73
Definition: multi_camera.h:24
absl::StatusOr< absl::flat_hash_map< std::string, std::vector< CameraMeasurement > > > Project(const std::vector< double > &interp_times, const Trajectory &sensorrig_trajectory, const WorldModel &world_model) const
Definition: multi_camera.cpp:186
absl::StatusOr< int > AddResidualsToProblem(ceres::Problem &problem, Trajectory &sensorrig_trajectory, WorldModel &world_model) final
Contribue this sensor's residuals to the ceres problem.
Definition: multi_camera.cpp:135
absl::Status SetImagerExtrinsics(const std::string &imager, const Pose3d &pose_sensor_from_imager)
Definition: multi_camera.cpp:40
absl::Status AddMeasurements(const std::string &imager, const std::vector< CameraMeasurement > &measurements)
Definition: multi_camera.cpp:260
absl::Status SetModel(const std::string &imager, CameraIntrinsicsModel camera_model)
Setter for the camera model.
Definition: multi_camera.cpp:10
absl::Status AddMeasurement(const std::string &imager, const CameraMeasurement &measurement)
Definition: multi_camera.cpp:244
const absl::flat_hash_map< std::string, absl::flat_hash_map< CameraObservationId, CameraMeasurement > > & GetMeasurementIdToMeasurement() const
Definition: multi_camera.h:192
void ClearMeasurements()
This will also clear any internally stored residuals and marked outliers.
Definition: multi_camera.cpp:331
absl::StatusOr< int > AddParametersToProblem(ceres::Problem &problem) final
Add this sensor's calibration parameters to the ceres problem.
Definition: multi_camera.cpp:98
absl::StatusOr< CameraIntrinsicsModel > GetModel(const std::string &imager) const
Getter for the camera model.
Definition: multi_camera.cpp:27
int NumberOfMeasurements(const std::string &imager) const
Get current number of measurements stored for a given imager.
Definition: multi_camera.cpp:346
absl::Status UpdateResiduals(ceres::Problem &problem) final
Update residuals for this sensor.
Definition: multi_camera.cpp:80
absl::StatusOr< absl::flat_hash_map< std::string, std::vector< std::pair< CameraMeasurement, Eigen::Vector2d > > > > GetMeasurementResidualPairs() const
Returns a vector of measurement-residual pairs.
Definition: multi_camera.cpp:278
void SetLossFunction(utils::LossFunctionType loss, double scale) final
Setter for loss function and scale.
Definition: multi_camera.h:129
void SetSensorExtrinsics(const Pose3d &pose_sensorrig_from_sensor)
Definition: multi_camera.h:62
absl::Status SetMeasurementNoise(double sigma) final
Set the measurement noise .
Definition: multi_camera.h:137
void ClearResidualInfo() final
Clear all stored info about residuals.
Definition: multi_camera.h:147
Definition: sensor_base.h:20
Sensors namespace.
Definition: accelerometer.cpp:8
CameraIntrinsicsModel
Camera model types.
Definition: camera_models.h:16
LossFunctionType
Definition: optimization_utils.h:15
Definition: camera.h:50