4141#include < glog/stl_logging.h>
4242#include < kimera_pgmo/utils/mesh_io.h>
4343
44- #include " hydra/common/global_info.h"
45- #include " hydra/common/launch_callbacks.h"
46- #include " hydra/common/pipeline_queues.h"
47- #include " hydra/utils/minimum_spanning_tree.h"
48- #include " hydra/utils/pgmo_mesh_traits.h"
44+ #include " hydra/utils/pgmo_mesh_traits.h" // IWYU pragma: keep
4945#include " hydra/utils/timing_utilities.h"
5046
5147namespace hydra {
48+ namespace {
49+
50+ void findAndApplyMerges (const VerbosityConfig& config,
51+ const UpdateFunctor::Hooks& hooks,
52+ const UpdateInfo::ConstPtr& info,
53+ const DynamicSceneGraph& source,
54+ SharedDsgInfo& target,
55+ MergeTracker& tracker,
56+ bool exhaustive) {
57+ // TODO(nathan) handle given merges
58+ auto merges = hooks.find_merges (source, info);
59+ auto applied = tracker.applyMerges (source, merges, target, hooks.merge );
60+ MLOG (1 ) << " pass 0: " << merges.size () << " merges (applied " << applied << " )" ;
61+ if (!exhaustive) {
62+ return ;
63+ }
64+
65+ applied = 0 ;
66+ size_t iter = 0 ;
67+ do {
68+ merges = hooks.find_merges (*target.graph , info);
69+ applied = tracker.applyMerges (source, merges, target, hooks.merge );
70+ MLOG (1 ) << " pass " << iter << " : " << merges.size () << " merges (applied "
71+ << applied << " )" ;
72+ ++iter;
73+ } while (applied > 0 );
74+ }
75+
76+ } // namespace
5277
5378using hydra::timing::ScopedTimer;
54- using kimera_pgmo::KimeraPgmoInterface;
55- using pose_graph_tools::PoseGraph;
79+
80+ DsgUpdater::Config::Config () : VerbosityConfig( " [dsg_updated] " ) {}
5681
5782void declare_config (DsgUpdater::Config& config) {
5883 using namespace config ;
5984 name (" DsgUpdaterConfig" );
6085 base<VerbosityConfig>(config);
86+ field (config.functor_logging , " functor_logging" );
6187 field (config.enable_node_merging , " enable_node_merging" );
62- field (config.enable_exhaustive_merging , " enable_exhaustive_merging" );
6388 field (config.reset_dsg_on_loop_closure , " reset_dsg_on_loop_closure" );
6489 field (config.update_functors , " update_functors" );
90+ field (config.exhaustive_functors , " exhaustive_functors" );
6591}
6692
6793DsgUpdater::DsgUpdater (const Config& config,
@@ -70,6 +96,7 @@ DsgUpdater::DsgUpdater(const Config& config,
7096 : config(config::checkValid(config)), source_graph_(source), target_dsg_(target) {
7197 for (const auto & [name, functor] : config.update_functors ) {
7298 update_functors_.emplace (name, functor.create ());
99+ merge_tracker.initializeTracker (name);
73100 }
74101}
75102
@@ -117,11 +144,28 @@ void DsgUpdater::callUpdateFunctions(size_t timestamp_ns, UpdateInfo::ConstPtr i
117144 if (config.reset_dsg_on_loop_closure && info->loop_closure_detected ) {
118145 resetBackendDsg (timestamp_ns);
119146 }
147+
120148 GraphMergeConfig merge_config;
121149 merge_config.previous_merges = &target_dsg_->merges ;
122150 merge_config.update_dynamic_attributes = false ;
123151 target_dsg_->graph ->mergeGraph (*source_graph_, merge_config);
124152
153+ // Nodes occasionally get added to the backend after they've left the active window,
154+ // which means they never get deformed or updated correctly. This forces them to be
155+ // active for at least one update
156+ std::vector<NodeId> active_nodes_to_restore;
157+ for (auto & [layer_id, layer] : source_graph_->layers ()) {
158+ for (auto & [node_id, node] : layer->nodes ()) {
159+ auto & attrs = node->attributes ();
160+ if (source_graph_->checkNode (node_id) == NodeStatus::NEW && !attrs.is_active ) {
161+ attrs.is_active = true ;
162+ active_nodes_to_restore.push_back (node_id);
163+ }
164+ }
165+ }
166+
167+ const std::set<std::string> exhaustive_names (config.exhaustive_functors .begin (),
168+ config.exhaustive_functors .end ());
125169 std::list<LayerCleanupFunc> cleanup_hooks;
126170 for (const auto & [name, functor] : update_functors_) {
127171 if (!functor) {
@@ -135,30 +179,39 @@ void DsgUpdater::callUpdateFunctions(size_t timestamp_ns, UpdateInfo::ConstPtr i
135179
136180 functor->call (*source_graph_, *target_dsg_, info);
137181 if (hooks.find_merges && enable_merging) {
138- // TODO(nathan) handle given merges
139- const auto merges = hooks.find_merges (*source_graph_, info);
140- const auto applied =
141- merge_tracker.applyMerges (*source_graph_, merges, *target_dsg_, hooks.merge );
142- MLOG (2 ) << " [Backend: " << name << " ] Found " << merges.size ()
143- << " merges (applied " << applied << " )" ;
144-
145- if (config.enable_exhaustive_merging ) {
146- size_t merge_iter = 0 ;
147- size_t num_applied = 0 ;
148- do {
149- const auto new_merges = hooks.find_merges (*target_dsg_->graph , info);
150- num_applied = merge_tracker.applyMerges (
151- *source_graph_, new_merges, *target_dsg_, hooks.merge );
152- MLOG (2 ) << " [Backend: " << name << " ] Found " << new_merges.size ()
153- << " merges at pass " << merge_iter << " (" << num_applied
154- << " applied)" ;
155- ++merge_iter;
156- } while (num_applied > 0 );
182+ auto & tracker = merge_tracker.getMergeGroup (name);
183+ findAndApplyMerges (config.functor_logging .with_name (name),
184+ hooks,
185+ info,
186+ *source_graph_,
187+ *target_dsg_,
188+ tracker,
189+ exhaustive_names.count (name));
190+ if (info->loop_closure_detected && hooks.merge ) {
191+ MLOG (3 ) << " updating all merge attributes for " << name;
192+ MLOG (3 ) << " current tracker: " << tracker.print ();
193+ tracker.updateAllMergeAttributes (
194+ *source_graph_, *target_dsg_->graph , hooks.merge );
157195 }
158196 }
159- }
160197
161- launchCallbacks (cleanup_hooks, info, target_dsg_.get ());
198+ MLOG (2 ) << " all merges: " << merge_tracker.print ();
199+ for (const auto & func : cleanup_hooks) {
200+ func (info, *source_graph_, target_dsg_.get ());
201+ }
202+
203+ // We reset active flags for all new nodes that were inactive after one update
204+ for (auto node_id : active_nodes_to_restore) {
205+ auto node = source_graph_->findNode (node_id);
206+ if (node) {
207+ node->attributes ().is_active = false ;
208+ }
209+ }
210+
211+ // clear new node status
212+ // TODO(nathan) add API for marking new nodes
213+ source_graph_->getNewNodes (true );
214+ }
162215}
163216
164217} // namespace hydra
0 commit comments