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" );
85+ base<VerbosityConfig>(config);
86+ field (config.functor_logging , " functor_logging" );
6087 field (config.enable_node_merging , " enable_node_merging" );
61- field (config.enable_exhaustive_merging , " enable_exhaustive_merging" );
6288 field (config.reset_dsg_on_loop_closure , " reset_dsg_on_loop_closure" );
6389 field (config.update_functors , " update_functors" );
90+ field (config.exhaustive_functors , " exhaustive_functors" );
6491}
6592
6693DsgUpdater::DsgUpdater (const Config& config,
@@ -69,6 +96,7 @@ DsgUpdater::DsgUpdater(const Config& config,
6996 : config(config::checkValid(config)), source_graph_(source), target_dsg_(target) {
7097 for (const auto & [name, functor] : config.update_functors ) {
7198 update_functors_.emplace (name, functor.create ());
99+ merge_tracker.initializeTracker (name);
72100 }
73101}
74102
@@ -116,11 +144,28 @@ void DsgUpdater::callUpdateFunctions(size_t timestamp_ns, UpdateInfo::ConstPtr i
116144 if (config.reset_dsg_on_loop_closure && info->loop_closure_detected ) {
117145 resetBackendDsg (timestamp_ns);
118146 }
147+
119148 GraphMergeConfig merge_config;
120149 merge_config.previous_merges = &target_dsg_->merges ;
121150 merge_config.update_dynamic_attributes = false ;
122151 target_dsg_->graph ->mergeGraph (*source_graph_, merge_config);
123152
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 ());
124169 std::list<LayerCleanupFunc> cleanup_hooks;
125170 for (const auto & [name, functor] : update_functors_) {
126171 if (!functor) {
@@ -134,30 +179,39 @@ void DsgUpdater::callUpdateFunctions(size_t timestamp_ns, UpdateInfo::ConstPtr i
134179
135180 functor->call (*source_graph_, *target_dsg_, info);
136181 if (hooks.find_merges && enable_merging) {
137- // TODO(nathan) handle given merges
138- const auto merges = hooks.find_merges (*source_graph_, info);
139- const auto applied =
140- merge_tracker.applyMerges (*source_graph_, merges, *target_dsg_, hooks.merge );
141- VLOG (1 ) << " [Backend: " << name << " ] Found " << merges.size ()
142- << " merges (applied " << applied << " )" ;
143-
144- if (config.enable_exhaustive_merging ) {
145- size_t merge_iter = 0 ;
146- size_t num_applied = 0 ;
147- do {
148- const auto new_merges = hooks.find_merges (*target_dsg_->graph , info);
149- num_applied = merge_tracker.applyMerges (
150- *source_graph_, new_merges, *target_dsg_, hooks.merge );
151- VLOG (1 ) << " [Backend: " << name << " ] Found " << new_merges.size ()
152- << " merges at pass " << merge_iter << " (" << num_applied
153- << " applied)" ;
154- ++merge_iter;
155- } 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 );
156195 }
157196 }
158- }
159197
160- 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+ }
161215}
162216
163217} // namespace hydra
0 commit comments