12 if (context.intrinsic_results.empty()) {
13 result.
summary[
"status"] =
"waiting_for_intrinsic_stage";
17 if (!context.has_bundle_config()) {
18 result.
summary[
"status"] =
"missing_config";
23 const auto& cfg = context.bundle_config();
24 if (cfg.rigs.empty()) {
25 result.
summary[
"status"] =
"no_rigs_configured";
32 context.bundle_results.clear();
33 if (!context.artifacts.is_object()) {
34 context.artifacts = nlohmann::json::object();
36 auto& bundle_artifacts = context.artifacts[
"bundle"];
37 if (!bundle_artifacts.is_object()) {
38 bundle_artifacts = nlohmann::json::object();
42 context.has_handeye_config() ? &context.handeye_config() :
nullptr;
44 bool overall_success =
true;
45 bool any_success =
false;
46 nlohmann::json rigs_json = nlohmann::json::array();
48 for (
const auto& rig : cfg.rigs) {
49 nlohmann::json rig_json;
50 rig_json[
"rig_id"] = rig.rig_id;
51 rig_json[
"sensor_count"] = rig.sensors.size();
52 rig_json[
"min_angle_deg"] = rig.min_angle_deg;
55 const std::size_t requested_views = observations !=
nullptr ? observations->size() : 0U;
57 if (observations ==
nullptr || observations->empty()) {
58 rig_json[
"status"] =
"no_observations";
59 rig_json[
"observations"] =
60 nlohmann::json::object({{
"requested", requested_views}, {
"used", 0}});
61 rigs_json.push_back(std::move(rig_json));
62 overall_success =
false;
66 auto& rig_artifact = bundle_artifacts[rig.rig_id];
67 if (!rig_artifact.is_object()) {
68 rig_artifact = nlohmann::json::object();
70 rig_artifact[
"options"] = rig.options;
71 rig_artifact[
"min_angle_deg"] = rig.min_angle_deg;
73 const auto sensor_setup =
75 if (!sensor_setup.missing_sensors.empty() ||
76 sensor_setup.cameras.size() != rig.sensors.size()) {
77 rig_json[
"status"] =
"missing_intrinsics";
78 rig_json[
"observations"] =
79 nlohmann::json::object({{
"requested", requested_views}, {
"used", 0}});
80 rigs_json.push_back(std::move(rig_json));
81 overall_success =
false;
86 *observations, rig.sensors, sensor_setup.sensor_to_index, sensor_index,
87 context.intrinsic_results);
89 rig_json[
"observations"] = nlohmann::json::object(
90 {{
"requested", requested_views}, {
"used", view_result.observations.size()}});
91 rig_json[
"views"] = view_result.views;
93 if (view_result.observations.empty()) {
94 rig_json[
"status"] =
"no_valid_observations";
95 rigs_json.push_back(std::move(rig_json));
96 overall_success =
false;
101 view_result.accumulators);
102 rig_json[
"handeye_initialization"] = handeye_init.report;
106 rig_json[
"initial_target_source"] = target_init.source;
108 rig_artifact[
"initial_hand_eye"] = handeye_init.report;
109 rig_artifact[
"initial_target"] = target_init.pose;
111 if (handeye_init.failed && !rig.initial_target.has_value()) {
112 overall_success =
false;
119 handeye_init.transforms, target_init.pose, options);
121 nlohmann::json result_json;
122 result_json[
"success"] = bundle_result.core.success;
123 result_json[
"final_cost"] = bundle_result.core.final_cost;
124 result_json[
"report"] = bundle_result.core.report;
125 result_json[
"b_se3_t"] = bundle_result.b_se3_t;
126 result_json[
"g_se3_c"] = bundle_result.g_se3_c;
127 result_json[
"cameras"] = bundle_result.cameras;
128 if (bundle_result.core.covariance.size() > 0) {
129 result_json[
"covariance"] = bundle_result.core.covariance;
132 rig_artifact[
"result"] = result_json;
133 rig_artifact[
"views"] = rig_json[
"views"];
135 rig_json[
"success"] = bundle_result.core.success;
136 rig_json[
"final_cost"] = bundle_result.core.final_cost;
138 if (bundle_result.core.success) {
139 rig_json[
"status"] =
"ok";
141 context.bundle_results[rig.rig_id] = bundle_result;
143 rig_json[
"status"] =
"optimization_failed";
144 overall_success =
false;
146 }
catch (
const std::exception& ex) {
147 rig_json[
"status"] =
"optimization_error";
148 rig_json[
"error"] = ex.what();
149 rig_artifact[
"error"] = ex.what();
150 overall_success =
false;
153 rigs_json.push_back(std::move(rig_json));
156 result.
summary[
"rigs"] = std::move(rigs_json);
157 if (any_success && overall_success) {
158 result.
summary[
"status"] =
"ok";
160 }
else if (any_success) {
161 result.
summary[
"status"] =
"partial_success";
164 result.
summary[
"status"] =
"failed";
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 optimize_bundle(const std::vector< BundleObservation > &observations, const std::vector< CameraT > &initial_cameras, const std::vector< Eigen::Isometry3d > &init_g_se3_c, const Eigen::Isometry3d &init_b_se3_t, const BundleOptions &opts={}) -> BundleResult< CameraT >
Perform bundle-adjustment style optimisation of the hand-eye calibration problem.