28 const std::size_t calibrated_cameras = context.intrinsic_results.size();
29 result.
summary[
"input_cameras"] = calibrated_cameras;
31 if (!context.has_stereo_config()) {
32 result.
summary[
"status"] =
"missing_config";
36 if (calibrated_cameras < 2) {
37 result.
summary[
"status"] =
"waiting_for_multiple_intrinsic_results";
42 const auto& stereo_cfg = context.stereo_config();
43 result.
summary[
"requested_pairs"] = stereo_cfg.pairs.size();
44 if (stereo_cfg.pairs.empty()) {
45 result.
summary[
"status"] =
"no_pairs_configured";
50 const auto detections_by_sensor = build_detection_lookup(context.dataset.planar_cameras);
52 if (!context.artifacts.is_object()) {
53 context.artifacts = nlohmann::json::object();
55 auto& stereo_artifacts = context.artifacts[
"stereo"];
56 if (!stereo_artifacts.is_object()) {
57 stereo_artifacts = nlohmann::json::object();
59 stereo_artifacts[
"pairs"] = nlohmann::json::object();
60 context.stereo_results.clear();
63 nlohmann::json pairs_summary = nlohmann::json::array();
65 bool all_success =
true;
66 bool any_success =
false;
68 for (
const auto& pair_cfg : stereo_cfg.pairs) {
69 nlohmann::json pair_json;
70 pair_json[
"pair_id"] = pair_cfg.pair_id;
71 pair_json[
"reference_sensor"] = pair_cfg.reference_sensor;
72 pair_json[
"target_sensor"] = pair_cfg.target_sensor;
73 pair_json[
"requested_views"] = pair_cfg.views.size();
75 const auto ref_intr_it = context.intrinsic_results.find(pair_cfg.reference_sensor);
76 const auto tgt_intr_it = context.intrinsic_results.find(pair_cfg.target_sensor);
78 if (ref_intr_it == context.intrinsic_results.end() ||
79 tgt_intr_it == context.intrinsic_results.end()) {
80 std::vector<std::string> missing;
81 if (ref_intr_it == context.intrinsic_results.end())
82 missing.push_back(pair_cfg.reference_sensor);
83 if (tgt_intr_it == context.intrinsic_results.end())
84 missing.push_back(pair_cfg.target_sensor);
85 pair_json[
"status"] =
"missing_intrinsics";
86 pair_json[
"missing"] = missing;
87 pair_json[
"success"] =
false;
89 pairs_summary.push_back(std::move(pair_json));
93 const auto ref_det_it = detections_by_sensor.find(pair_cfg.reference_sensor);
94 const auto tgt_det_it = detections_by_sensor.find(pair_cfg.target_sensor);
95 if (ref_det_it == detections_by_sensor.end() || tgt_det_it == detections_by_sensor.end()) {
96 std::vector<std::string> missing;
97 if (ref_det_it == detections_by_sensor.end())
98 missing.push_back(pair_cfg.reference_sensor);
99 if (tgt_det_it == detections_by_sensor.end()) missing.push_back(pair_cfg.target_sensor);
100 pair_json[
"status"] =
"missing_detections";
101 pair_json[
"missing"] = missing;
102 pair_json[
"success"] =
false;
104 pairs_summary.push_back(std::move(pair_json));
109 auto pair_result = facade.
calibrate(pair_cfg, *ref_det_it->second, *tgt_det_it->second,
110 ref_intr_it->second, tgt_intr_it->second);
112 pair_json[
"views"] = pair_result.view_summaries;
113 pair_json[
"used_views"] = pair_result.used_views;
114 pair_json[
"success"] = pair_result.success;
115 pair_json[
"status"] = pair_result.success ?
"ok" :
"failed";
116 pair_json[
"final_cost"] = pair_result.optimization.core.final_cost;
118 if (pair_result.success) {
120 context.stereo_results[pair_cfg.pair_id] = pair_result.optimization;
125 nlohmann::json initial_guess_json;
126 nlohmann::json cams_json = nlohmann::json::array();
127 std::copy(pair_result.initial_guess.c_se3_r.begin(),
128 pair_result.initial_guess.c_se3_r.end(), std::back_inserter(cams_json));
129 nlohmann::json targets_json = nlohmann::json::array();
130 std::copy(pair_result.initial_guess.r_se3_t.begin(),
131 pair_result.initial_guess.r_se3_t.end(), std::back_inserter(targets_json));
132 initial_guess_json[
"c_se3_r"] = std::move(cams_json);
133 initial_guess_json[
"r_se3_t"] = std::move(targets_json);
135 nlohmann::json artifact;
136 artifact[
"initial_guess"] = std::move(initial_guess_json);
137 artifact[
"views"] = pair_json[
"views"];
138 artifact[
"optimization"] = pair_result.optimization;
139 artifact[
"final_cost"] = pair_result.optimization.core.final_cost;
140 stereo_artifacts[
"pairs"][pair_cfg.pair_id] = std::move(artifact);
141 }
catch (
const std::exception& ex) {
142 pair_json[
"status"] =
"calibration_error";
143 pair_json[
"error"] = ex.what();
144 pair_json[
"success"] =
false;
148 pairs_summary.push_back(std::move(pair_json));
151 result.
summary[
"pairs"] = std::move(pairs_summary);
152 if (any_success && all_success) {
153 result.
summary[
"status"] =
"ok";
155 }
else if (any_success) {
156 result.
summary[
"status"] =
"partial_success";
159 result.
summary[
"status"] =
"failed";