optimize
메서드는 루프 클로저가 감지되었을 때 메쉬 변형과 그래프 최적화를 수행합니다.optimize
메서드 상세 분석BackendModule
클래스의 optimize
메서드는 로봇 시스템의 백엔드에서 메쉬 변형(Mesh Deformation)과 그래프 최적화(Graph Optimization)를 수행하는 핵심적인 함수입니다. 이 메서드는 루프 클로저(Loop Closure)가 감지되었을 때 호출되며, 환경의 지도를 정교화하고 오류를 보정하기 위해 메쉬와 그래프 구조를 업데이트합니다.
optimize
메서드는 다음과 같은 주요 작업을 수행합니다:
각 단계는 시스템의 정확성과 일관성을 유지하기 위해 중요한 역할을 합니다. 아래에서는 각 단계의 동작과 관련 함수들의 역할을 상세히 설명하겠습니다.
환경의 장소 노드를 변형 그래프에 추가하여, 메쉬 변형 과정에서 장소 노드의 위치 정보가 반영되도록 합니다. 이는 메쉬 변형이 공간적으로 일관되게 이루어지도록 보장하며, 장소 노드와 메쉬 간의 관계를 유지합니다.
add_places_to_deformation_graph
옵션이 활성화되어 있는지 확인합니다.addPlacesToDeformationGraph(timestamp_ns)
를 호출하여 장소 노드를 변형 그래프에 추가합니다.addPlacesToDeformationGraph
함수 상세 설명주요 작업:
세부 동작:
변형 그래프에 장소 노드 추가:
gtsam::Pose3
객체로 변환하여 저장합니다.변형 그래프에 엣지 추가:
변형 그래프를 최적화하여 메쉬 변형에 필요한 제어점(Control Points)의 위치를 업데이트합니다. 이를 통해 루프 클로저로 인해 발생한 지도의 왜곡을 보정하고, 전체적인 일관성을 유지합니다.
deformation_graph_->optimize()
를 호출하여 변형 그래프를 최적화합니다.DeformationGraph::optimize
함수 상세 설명주요 작업:
pgo_->forceUpdate(new_factors_, new_values_);
를 호출하여, 새로운 팩터(factors)와 변수(values)를 그래프에 강제로 적용합니다.force_recalculate_
플래그가 설정되어 있으면, 정점의 재계산이 필요함을 표시하는 recalculate_vertices_
를 true
로 설정합니다.values_ = pgo_->calculateEstimate();
를 호출하여, 최적화된 변수들의 값을 계산합니다.new_factors_
와 new_values_
를 초기화하여, 다음 최적화를 준비합니다.참고 사항:
최적화된 변형 그래프의 결과를 바탕으로 DSG의 메쉬를 업데이트하여, 환경의 지도를 최신 상태로 유지합니다. 이는 메쉬 변형을 통해 지도의 왜곡을 보정하고, 노드 간의 공간적 관계를 일관성 있게 유지합니다.
force_mesh_update
가 false
이고 have_new_mesh_
가 false
이면, 업데이트를 수행하지 않습니다.force_mesh_update
가 false
이고 루프 클로저가 발생하지 않은 경우에도 업데이트를 생략합니다.deformation_graph_->deformPoints
를 호출하여 메쉬의 정점들을 변형합니다.original_vertices_
)과 타임스탬프(vertex_stamps_
)를 제공합니다.getGtsamValues()
)을 사용하여 변형을 적용합니다.prev_num_archived_vertices_
를 현재의 num_archived_vertices_
로 업데이트하여, 다음 변형 시 사용할 수 있도록 합니다.DeformationGraph::deformPoints
함수 상세 설명주요 작업:
k
개 제어점을 사용하여 가중치를 계산하고, 정점의 새로운 위치를 결정합니다.세부 동작:
참고 사항:
최적화된 결과를 기반으로 DSG(Dynamic Scene Graph)의 구조와 속성을 업데이트하고, 관련된 모듈이나 함수들을 호출하여 시스템 전체의 일관성을 유지합니다. 특히, 각 레이어의 업데이트 함수와 에이전트 업데이트 함수를 호출하여 그래프의 각 구성 요소를 갱신합니다.
void BackendModule::optimize(size_t timestamp_ns) {
// ... 이전 단계 코드 생략 ...
// 4. 업데이트된 정보를 기반으로 다른 모듈 호출
callUpdateFunctions(timestamp_ns,
deformation_graph_->getGtsamTempValues(),
deformation_graph_->getGtsamValues(),
have_new_loopclosures_);
have_new_loopclosures_ = false;
}
optimize
메서드의 마지막 부분에서 callUpdateFunctions
함수를 호출합니다. 이 함수가 다른 모듈들을 호출하여 DSG를 업데이트하는 핵심 부분입니다.
callUpdateFunctions
함수의 상세 동작void BackendModule::callUpdateFunctions(size_t timestamp_ns,
const gtsam::Values& places_values,
const gtsam::Values& pgmo_values,
bool new_loop_closure,
const UpdateInfo::LayerMerges& given_merges) {
// 타이머 시작
ScopedTimer spin_timer("backend/update_layers", timestamp_ns);
// 병합 활성화 여부 결정
const bool enable_merging = given_merges.empty() ? config.enable_node_merging : false;
// 에이전트 값 준비
gtsam::Values complete_agent_values;
// ... 에이전트 값 설정 코드 생략 ...
// UpdateInfo 객체 생성
UpdateInfo::ConstPtr info(new UpdateInfo{&places_values,
&pgmo_values,
new_loop_closure,
timestamp_ns,
enable_merging,
given_merges,
&complete_agent_values});
// 그래프 병합 수행
GraphMergeConfig config;
config.previous_merges = &private_dsg_->merges;
config.update_dynamic_attributes = false;
private_dsg_->graph->mergeGraph(*unmerged_graph_, config);
// 에이전트 업데이트 함수 호출
if (agent_functor_) {
agent_functor_->call(*unmerged_graph_, *private_dsg_, info);
}
// 레이어별 업데이트 함수 호출 및 병합 처리
std::list<LayerCleanupFunc> cleanup_hooks;
for (const auto& [layer, functor] : layer_functors_) {
if (!functor) {
continue;
}
const auto merges = functor->call(*unmerged_graph_, *private_dsg_, info);
const auto hooks = functor->hooks();
merge_tracker.applyMerges(*unmerged_graph_, merges, *private_dsg_, hooks.merge);
if (hooks.cleanup) {
cleanup_hooks.push_back(hooks.cleanup);
}
}
// 콜백 실행
launchCallbacks(cleanup_hooks, info, private_dsg_.get());
}
unmerged_graph_
를 private_dsg_->graph
에 병합합니다.GraphMergeConfig
를 설정하여 병합 과정에서의 세부 동작을 제어합니다.mergeGraph
함수를 호출하여 그래프를 병합합니다.agent_functor_
)agent_functor_
가 설정되어 있을 때 호출됩니다.agent_functor_->call(*unmerged_graph_, *private_dsg_, info);
를 호출하여 에이전트 레이어를 업데이트합니다.layer_functors_
)layer_functors_
에 저장된 각 레이어의 업데이트 함수를 순회하며 호출합니다.functor->call(*unmerged_graph_, *private_dsg_, info);
를 통해 레이어를 업데이트합니다.merge_tracker.applyMerges
를 통해 적용합니다.launchCallbacks(cleanup_hooks, info, private_dsg_.get());
를 호출하여 콜백 함수를 실행합니다.agent_functor_
)BackendModule
생성 시 또는 외부에서 agent_functor_
를 설정합니다.if (agent_functor_) {
agent_functor_->call(*unmerged_graph_, *private_dsg_, info);
}
layer_functors_
)역할: DSG의 각 레이어를 업데이트하고, 필요한 경우 노드 병합 등을 수행합니다.
설정된 기본 업데이트 함수들:
DsgLayers::OBJECTS
):UpdateObjectsFunctor
DsgLayers::PLACES
):UpdatePlacesFunctor
DsgLayers::ROOMS
):UpdateRoomsFunctor
DsgLayers::BUILDINGS
):UpdateBuildingsFunctor
관련 코드:
for (const auto& [layer, functor] : layer_functors_) {
if (!functor) {
continue;
}
const auto merges = functor->call(*unmerged_graph_, *private_dsg_, info);
// 병합 처리 및 콜백 수집
}
UpdateObjectsFunctor
:
UpdatePlacesFunctor
:
UpdateRoomsFunctor
:
UpdateBuildingsFunctor
:
병합 처리:
merge_tracker.applyMerges
를 통해 적용합니다.콜백 실행:
BackendModule::optimize
메서드의 4번 단계에서, DSG의 각 레이어를 업데이트하기 위해 다양한 모듈들이 호출됩니다.이로써 BackendModule::optimize
메서드의 '4. 업데이트된 정보를 기반으로 다른 모듈 호출' 단계에서 어떤 다른 모듈이 호출되는지에 대한 상세한 설명을 제공하였습니다.