13 const std::unordered_map<std::string, IntrinsicCalibrationOutputs>& intrinsics)
16 setup.
cameras.reserve(rig.sensors.size());
17 for (std::size_t idx = 0; idx < rig.sensors.size(); ++idx) {
18 const auto& sensor_id = rig.sensors[idx];
19 const auto intrinsics_it = intrinsics.find(sensor_id);
20 if (intrinsics_it == intrinsics.end()) {
25 setup.
cameras.push_back(intrinsics_it->second.refine_result.camera);
47 const std::vector<HandEyeObservationConfig>& observation_config,
48 const std::vector<std::string>& sensors,
49 const std::unordered_map<std::string, std::size_t>& sensor_to_index,
50 const std::unordered_map<std::string, SensorDetectionsIndex>& sensor_index,
51 const std::unordered_map<std::string, IntrinsicCalibrationOutputs>& intrinsics)
54 output.
views = nlohmann::json::array();
57 for (
const auto& view_cfg : observation_config) {
58 nlohmann::json view_json;
59 if (!view_cfg.view_id.empty()) {
60 view_json[
"id"] = view_cfg.view_id;
62 view_json[
"base_pose"] = view_cfg.base_se3_gripper;
64 nlohmann::json sensor_reports = nlohmann::json::array();
65 bool view_used =
false;
67 for (
const auto& sensor_id : sensors) {
68 nlohmann::json sensor_entry;
69 sensor_entry[
"sensor_id"] = sensor_id;
71 const auto sensor_idx_it = sensor_to_index.find(sensor_id);
72 if (sensor_idx_it == sensor_to_index.end()) {
73 sensor_entry[
"status"] =
"sensor_not_configured";
74 sensor_reports.push_back(std::move(sensor_entry));
77 const std::size_t sensor_idx = sensor_idx_it->second;
79 const auto image_it = view_cfg.images.find(sensor_id);
80 if (image_it == view_cfg.images.end()) {
81 sensor_entry[
"status"] =
"missing_image_reference";
82 sensor_reports.push_back(std::move(sensor_entry));
86 const auto det_index_it = sensor_index.find(sensor_id);
87 if (det_index_it == sensor_index.end()) {
88 sensor_entry[
"status"] =
"missing_detections";
89 sensor_reports.push_back(std::move(sensor_entry));
93 const auto lookup_it = det_index_it->second.image_lookup.find(image_it->second);
94 if (lookup_it == det_index_it->second.image_lookup.end()) {
95 sensor_entry[
"status"] =
"image_not_in_dataset";
96 sensor_entry[
"image"] = image_it->second;
97 sensor_reports.push_back(std::move(sensor_entry));
101 const auto intrinsics_it = intrinsics.find(sensor_id);
102 if (intrinsics_it == intrinsics.end()) {
103 sensor_entry[
"status"] =
"missing_intrinsics";
104 sensor_reports.push_back(std::move(sensor_entry));
107 const auto& camera = intrinsics_it->second.refine_result.camera;
109 const auto* image_det = lookup_it->second;
112 sensor_entry[
"image"] = image_it->second;
113 sensor_entry[
"points"] = planar_view.size();
115 if (planar_view.size() < 4U) {
116 sensor_entry[
"status"] =
"insufficient_points";
117 sensor_reports.push_back(std::move(sensor_entry));
124 obs.
view = std::move(planar_view);
125 obs.
b_se3_g = view_cfg.base_se3_gripper;
129 output.
accumulators[sensor_idx].base.push_back(view_cfg.base_se3_gripper);
130 output.
accumulators[sensor_idx].cam.push_back(cam_se3_target);
132 sensor_entry[
"status"] =
"ok";
134 sensor_reports.push_back(std::move(sensor_entry));
137 view_json[
"sensors"] = std::move(sensor_reports);
138 view_json[
"used"] = view_used;
139 output.
views.push_back(std::move(view_json));
150 const std::unordered_map<std::string, std::unordered_map<std::string, HandeyeResult>>&
154 output.
report = nlohmann::json::array();
155 output.
transforms.assign(rig.sensors.size(), Eigen::Isometry3d::Identity());
157 const auto rig_handeye_it = handeye_results.find(rig.rig_id);
158 const auto* sensor_map =
159 rig_handeye_it != handeye_results.end() ? &rig_handeye_it->second :
nullptr;
161 for (std::size_t idx = 0; idx < rig.sensors.size(); ++idx) {
162 const auto& sensor_id = rig.sensors[idx];
163 nlohmann::json entry;
164 entry[
"sensor_id"] = sensor_id;
165 entry[
"source"] =
"identity";
167 if (sensor_map !=
nullptr) {
168 const auto he_it = sensor_map->find(sensor_id);
169 if (he_it != sensor_map->end() && he_it->second.core.success) {
170 output.
transforms[idx] = he_it->second.g_se3_c;
171 entry[
"source"] =
"handeye";
172 entry[
"success"] =
true;
173 output.
report.push_back(std::move(entry));
178 if (idx < accumulators.size() && accumulators[idx].cam.size() >= 2U) {
181 accumulators[idx].
base, accumulators[idx].
cam, rig.min_angle_deg);
182 entry[
"source"] =
"dlt";
183 entry[
"success"] =
true;
184 }
catch (
const std::exception& ex) {
185 entry[
"source"] =
"dlt";
186 entry[
"success"] =
false;
187 entry[
"error"] = ex.what();
191 entry[
"success"] =
false;
192 entry[
"error"] =
"insufficient_observations";
196 output.
report.push_back(std::move(entry));
203 const std::vector<SensorAccumulator>& accumulators,
204 const std::vector<Eigen::Isometry3d>& init_g_se3_c)
208 if (rig.initial_target.has_value()) {
209 output.
pose = *rig.initial_target;
214 std::vector<Eigen::Isometry3d> candidates;
215 for (std::size_t idx = 0; idx < accumulators.size(); ++idx) {
216 const auto& acc = accumulators[idx];
217 if (idx >= init_g_se3_c.size()) {
220 const auto& g_pose = init_g_se3_c[idx];
221 for (std::size_t obs_idx = 0; obs_idx < acc.base.size(); ++obs_idx) {
222 const auto& base_pose = acc.base[obs_idx];
223 const auto& cam_pose = acc.cam[obs_idx];
224 candidates.push_back(base_pose * g_pose * cam_pose);
228 if (!candidates.empty()) {
230 output.
source =
"estimated";
232 output.
pose = Eigen::Isometry3d::Identity();
233 output.
source =
"identity";
auto collect_bundle_observations(const std::vector< HandEyeObservationConfig > &observation_config, const std::vector< std::string > &sensors, const std::unordered_map< std::string, std::size_t > &sensor_to_index, const std::unordered_map< std::string, SensorDetectionsIndex > &sensor_index, const std::unordered_map< std::string, IntrinsicCalibrationOutputs > &intrinsics) -> BundleViewProcessingResult
auto estimate_handeye_dlt(const std::vector< Eigen::Isometry3d > &base_se3_gripper, const std::vector< Eigen::Isometry3d > &camera_se3_target, double min_angle_deg=1.0) -> Eigen::Isometry3d
Estimates the hand-eye transformation using the Tsai-Lenz algorithm with all pairs of input transform...