@@ -12,16 +12,15 @@ namespace distributed_pcm {
1212 std::vector<graph_utils::Transforms> transforms_by_robot;
1313 std::map<std::pair<char , char >,graph_utils::Transforms> separators_transforms_by_pair;
1414
15- fillInRequiredInformation (separators_by_robot, transforms_by_robot, separators_transforms_by_pair,
15+ fillInRequiredInformationCentralized (separators_by_robot, transforms_by_robot, separators_transforms_by_pair,
1616 dist_mappers, use_covariance);
1717
1818 // Apply PCM for each pair of robots
19- // For now I will work with perfect information
2019 int total_max_clique_sizes = 0 ;
2120 for (int roboti = 0 ; roboti < dist_mappers.size (); roboti++) {
2221 for (int robotj = roboti+1 ; robotj < dist_mappers.size (); robotj++) {
2322
24- int max_clique_size = executePCM (roboti, robotj, transforms_by_robot, separators_by_robot,
23+ int max_clique_size = executePCMCentralized (roboti, robotj, transforms_by_robot, separators_by_robot,
2524 separators_transforms_by_pair, dist_mappers,
2625 graph_and_values_vector, confidence_probability);
2726
@@ -32,7 +31,30 @@ namespace distributed_pcm {
3231 return total_max_clique_sizes;
3332 }
3433
35- void DistributedPCM::fillInRequiredInformation (std::vector<graph_utils::LoopClosures>& separators_by_robot,
34+ int DistributedPCM::solveDecentralized (const int & other_robot_id,
35+ boost::shared_ptr<distributed_mapper::DistributedMapper>& dist_mapper,
36+ gtsam::GraphAndValues& local_graph_and_values,
37+ const gtsam::Values& other_robot_poses,
38+ const double & confidence_probability, const bool & use_covariance) {
39+
40+ graph_utils::LoopClosures separators;
41+ graph_utils::Transforms transforms;
42+ graph_utils::Trajectory other_robot_trajectory;
43+ graph_utils::Transforms separators_transforms;
44+
45+ fillInRequiredInformationDecentralized (separators, transforms, other_robot_trajectory, separators_transforms,
46+ dist_mapper, other_robot_poses, other_robot_id, use_covariance);
47+
48+ // Apply PCM for each pair of robots
49+ int max_clique_size = executePCMDecentralized (other_robot_id, transforms,
50+ separators, other_robot_trajectory,
51+ separators_transforms, dist_mapper,
52+ local_graph_and_values, confidence_probability);
53+
54+ return max_clique_size;
55+ }
56+
57+ void DistributedPCM::fillInRequiredInformationCentralized (std::vector<graph_utils::LoopClosures>& separators_by_robot,
3658 std::vector<graph_utils::Transforms>& transforms_by_robot,
3759 std::map<std::pair<char , char >,graph_utils::Transforms>& separators_transforms_by_pair,
3860 const std::vector< boost::shared_ptr<distributed_mapper::DistributedMapper> >& dist_mappers,
@@ -93,7 +115,84 @@ namespace distributed_pcm {
93115 }
94116 }
95117
96- int DistributedPCM::executePCM (const int & roboti, const int & robotj, const std::vector<graph_utils::Transforms>& transforms_by_robot,
118+ void DistributedPCM::fillInRequiredInformationDecentralized (graph_utils::LoopClosures& separators,
119+ graph_utils::Transforms& transforms,
120+ graph_utils::Trajectory& other_robot_trajectory,
121+ graph_utils::Transforms& separators_transforms,
122+ const boost::shared_ptr<distributed_mapper::DistributedMapper>& dist_mapper,
123+ const gtsam::Values& other_robot_poses,
124+ const int & other_robot_id,
125+ const bool & use_covariance){
126+ // Store separators key pairs
127+ for (auto id : dist_mapper->separatorEdge ()) {
128+ auto separator_edge = boost::dynamic_pointer_cast<gtsam::BetweenFactor<gtsam::Pose3> >(
129+ dist_mapper->currentGraph ().at (id));
130+ separators.emplace_back (std::make_pair (separator_edge->key1 (), separator_edge->key2 ()));
131+ }
132+
133+ bool id_initialized = false ;
134+ for (const auto & factor_ptr : dist_mapper->currentGraph ()) {
135+ auto edge_ptr = boost::dynamic_pointer_cast<gtsam::BetweenFactor<gtsam::Pose3> >(factor_ptr);
136+ if (edge_ptr) { // Do nothing with the prior in the first robot graph
137+ graph_utils::Transform transform;
138+ transform.i = edge_ptr->key1 ();
139+ transform.j = edge_ptr->key2 ();
140+ transform.pose .pose = edge_ptr->measured ();
141+ if (use_covariance) {
142+ transform.pose .covariance_matrix =
143+ boost::dynamic_pointer_cast< gtsam::noiseModel::Gaussian >(edge_ptr->noiseModel ())->covariance ();
144+ } else {
145+ transform.pose .covariance_matrix = graph_utils::FIXED_COVARIANCE;
146+ }
147+ transform.is_separator = std::find (separators.begin (), separators.end (),
148+ std::make_pair (edge_ptr->key1 (), edge_ptr->key2 ())) !=
149+ separators.end ();
150+ if (!transform.is_separator ) {
151+ if (!id_initialized) {
152+ transforms.start_id = transform.i ;
153+ transforms.end_id = transform.j ;
154+ id_initialized = true ;
155+ } else {
156+ transforms.start_id = std::min (transforms.start_id , transform.i );
157+ transforms.end_id = std::max (transforms.end_id , transform.j );
158+ }
159+ transforms.transforms .insert (
160+ std::make_pair (std::make_pair (edge_ptr->key1 (), edge_ptr->key2 ()), transform));
161+ } else {
162+ auto id_1 = gtsam::Symbol (edge_ptr->key1 ()).chr ()-97 ;
163+ auto id_2 = gtsam::Symbol (edge_ptr->key2 ()).chr ()-97 ;
164+ if (id_1 == other_robot_id || id_2 == other_robot_id) {
165+ separators_transforms.transforms .insert (
166+ std::make_pair (std::make_pair (edge_ptr->key1 (), edge_ptr->key2 ()), transform));
167+ }
168+ }
169+ }
170+ }
171+
172+ // Fill in the other robot poses in a trajectory structure
173+ gtsam::Key first_key, last_key;
174+ bool init_first = false ;
175+ bool init_last = false ;
176+ for (const gtsam::Values::ConstKeyValuePair& key_value_pair : other_robot_poses) {
177+ if (first_key > key_value_pair.key || !init_first) {
178+ first_key = key_value_pair.key ;
179+ init_first = true ;
180+ }
181+ if (last_key < key_value_pair.key || !init_last) {
182+ last_key = key_value_pair.key ;
183+ init_last = true ;
184+ }
185+
186+ graph_utils::TrajectoryPose trajectory_pose;
187+ trajectory_pose.id = key_value_pair.key ;
188+ trajectory_pose.pose .pose = other_robot_poses.at <gtsam::Pose3>(key_value_pair.key );
189+ other_robot_trajectory.trajectory_poses .insert (std::make_pair (key_value_pair.key , trajectory_pose));
190+ }
191+ other_robot_trajectory.start_id = first_key;
192+ other_robot_trajectory.end_id = last_key;
193+ }
194+
195+ int DistributedPCM::executePCMCentralized (const int & roboti, const int & robotj, const std::vector<graph_utils::Transforms>& transforms_by_robot,
97196 const std::vector<graph_utils::LoopClosures>& separators_by_robot,
98197 const std::map<std::pair<char , char >,graph_utils::Transforms>& separators_transforms_by_pair,
99198 std::vector< boost::shared_ptr<distributed_mapper::DistributedMapper> >& dist_mappers,
@@ -146,6 +245,61 @@ namespace distributed_pcm {
146245 return max_clique.size ();
147246 }
148247
248+ int DistributedPCM::executePCMDecentralized (const int & other_robot_id, const graph_utils::Transforms& transforms,
249+ const graph_utils::LoopClosures& separators,
250+ const graph_utils::Trajectory& other_robot_trajectory,
251+ const graph_utils::Transforms& separators_transforms,
252+ boost::shared_ptr<distributed_mapper::DistributedMapper>& dist_mapper,
253+ gtsam::GraphAndValues& local_graph_and_values,
254+ const double & confidence_probability){
255+
256+ auto robot_local_map = robot_measurements::RobotLocalMap (transforms, separators);
257+ graph_utils::Transforms empty_transforms;
258+ auto other_robot_local_info = robot_measurements::RobotLocalMap (other_robot_trajectory, empty_transforms, separators);
259+ auto roboti_robotj_separators_transforms = separators_transforms;
260+ auto interrobot_measurements = robot_measurements::InterRobotMeasurements (roboti_robotj_separators_transforms,
261+ dist_mapper->robotName (), ((char ) other_robot_id + 97 ));
262+
263+ auto global_map = global_map::GlobalMap (robot_local_map, other_robot_local_info, interrobot_measurements, confidence_probability);
264+ std::vector<int > max_clique = global_map.pairwiseConsistencyMaximization ();
265+
266+ // Retrieve indexes of rejected measurements
267+ auto separators_ids = dist_mapper->separatorEdge ();
268+ std::vector<int > rejected_separator_ids;
269+ for (int i = 0 ; i < separators_ids.size (); i++) {
270+ if (isSeparatorToBeRejected (max_clique, separators_ids[i], roboti_robotj_separators_transforms,
271+ interrobot_measurements.getLoopClosures (), dist_mapper)) {
272+ rejected_separator_ids.emplace_back (i);
273+ }
274+ }
275+ // Remove measurements not in the max clique
276+ int number_separator_ids_removed = 0 ;
277+ for (const auto & index : rejected_separator_ids) {
278+ auto id = separators_ids[index] - number_separator_ids_removed;
279+ number_separator_ids_removed++;
280+ dist_mapper->eraseFactor (id);
281+ local_graph_and_values.first ->erase (local_graph_and_values.first ->begin ()+id);
282+ }
283+ // Update separator ids
284+ std::vector<size_t > new_separator_ids;
285+ int number_of_edges = dist_mapper->currentGraph ().size ();
286+ if (((int ) dist_mapper->robotName ()-97 ) == 0 ){
287+ // Do not count the prior in the first robot graph
288+ number_of_edges--;
289+ }
290+ for (int i = 0 ; i < number_of_edges; i++) {
291+ auto keys = dist_mapper->currentGraph ().at (i)->keys ();
292+ char robot0 = gtsam::symbolChr (keys.at (0 ));
293+ char robot1 = gtsam::symbolChr (keys.at (1 ));
294+ if (robot0 != robot1) {
295+ new_separator_ids.push_back (i);
296+ }
297+ }
298+ dist_mapper->setSeparatorIds (new_separator_ids);
299+
300+ return max_clique.size ();
301+ }
302+
149303 bool DistributedPCM::isSeparatorToBeRejected (const std::vector<int >& max_clique, const int & separtor_id, const graph_utils::Transforms& separators_transforms,
150304 const graph_utils::LoopClosures& loop_closures, boost::shared_ptr<distributed_mapper::DistributedMapper>& dist_mapper) {
151305
0 commit comments