업데이트 된 object
- place 간 연결 수정 (가장 가까운 place를 찾아 연결)2d
places를 도출kimera_pgmo::MeshCompression
(deformation_compression_
) 에서, 오래된 mesh 제거kimera_pgmo::MeshCompression
(deformation_compression_
)에 추가한 후, 압축kimera_pgmo::Graph
(deformation_graph_
)에, 위 과정에서 새로 생성된 압축된 mesh 면
(삼각형, 꼭지점)들을 그래프 형태(노드 + 엣지)로 변환하여 추가해줌kimera_pgmo::Graph
(deformation_graph_
)에 추가된 새 압축된 edge들
을 이용해서, PoseGraph를 만듭니다.새롭게 추가된 mesh 정보들
을 담고 있습니다.갱신된 포즈 그래프를 포함한 PoseGraphPacket 형태를 반환
하여 lcd_input_
(new_agent_nodes 맴버 변수)에 추가addPlaceAgentEdges
assignBowVectors
특정 단어 ID
와 해당 단어의 가중치
로 구성place nodes
)를 원래 그래프에 반영Place(3) - Agent(2) 엣지
를 새로 조정하고, Place(3)-object(2) 엣지
를 새로 조정합니다.frontier_places_.updateRecentBlocks
freespace_places_.getActiveNodes
frontier_places_.detectFrontiers
frontier_places_.addFrontiers
이전에 탐색된 Frontiers 노드들을 DSG 그래프의 place node에서 제거해.
새롭게 탐지된 경계 추가
nodes_to_remove_
목록에 저장해, 다음 탐색에서 정리될 수 있도록 준비해.아카이브된 경계 추가
PlaceMeshConnector
객체를 생성하여,변형(deformation) 연결 정보
와 레이블(semantics)
을 할당 state_
->backend_graph
) 에 프론트엔드에서 처리한 현재 그래프(dsg_
->graph)를 병합backend_input_
lcd_input_
백엔드와 LCD
에 전달queue_
(입력 대기열)에서 데이터를 폴링하여 ReconstructionOutput을 처리하는 메서드bool FrontendModule::spinOnce() {
bool has_data = queue_->poll();
if (!has_data) {
return false;
}
ReconstructionOutput::Ptr input = queue_->front();
processNextInput(*input);
queue_->pop();
spinOnce(input);
return true;
}
queue_->poll(): 큐에서 데이터를 기다리며, 데이터가 있으면 true
를 반환하고 없으면 false
를 반환합니다.
queue_->front(): 큐의 첫 번째 요소, 즉 가장 최근의 ReconstructionOutput 데이터를 가져옵니다.
processNextInput(): 아무것도 구현되어 있지 않음.
queue_->pop(): 큐에서 첫 번째 입력을 제거합니다. 입력이 처리되었으므로 큐에서 제거하는 것입니다.
spinOnce(input): 입력 데이터를 더 구체적으로 처리하기 위해 spinOnce
함수의 또 다른 오버로드된 버전을 호출
void FrontendModule::spinOnce(const ReconstructionOutput::Ptr& msg)
- 코드 상void FrontendModule::spinOnce(const ReconstructionOutput::Ptr& msg) {
if (!initialized_) {
initCallbacks();
}
VLOG(5) << "[Hydra Frontend] Popped input packet @ " << msg->timestamp_ns << " [ns]";
std::lock_guard<std::mutex> lock(mutex_);
ScopedTimer timer("frontend/spin", msg->timestamp_ns);
backend_input_.reset(new BackendInput());
backend_input_->timestamp_ns = msg->timestamp_ns;
if (state_->lcd_queue) {
lcd_input_.reset(new LcdInput());
lcd_input_->timestamp_ns = msg->timestamp_ns;
}
updateImpl(msg);
초기화:
backend_input_
초기화:
lcd_input_
초기화 (옵션):
struct LcdInput {
using Ptr = std::shared_ptr<LcdInput>;
uint64_t timestamp_ns;
NodeIdSet archived_places;
std::vector<NodeId> new_agent_nodes;
};
3.2. updateImpl(msg)
함수는 현재 입력 데이터를 사용하여 내부 상태를 업데이트하고, 필요한 모든 처리를 실행input_callbacks_
)input_callbacks_
리스트에 5개의 주요 콜백 함수를 추가
updateMesh
등록post_mesh_callbacks_
)updateObjects
등록updatePlaces2d
등록updateDeformationGraph
등록updateDeformationGraph()
는 변형 그래프를 업데이트하는 함수updatePoseGraph
등록updatePlaces
등록updateFrontiers
등록updateFrontiers()
는 로봇이 탐지한 경계 지역(Frontiers)을 업데이트하는 함수input_dispatches_
초기화: input_callbacks_
에 있는 콜백 함수들을 디스패치 함수 형태로 input_dispatches_
에 저장하여, 동적으로 호출할 수 있도록 준비launchCallbacks()
를 통해 각 콜백 함수를 실행하여, void FrontendModule::spinOnce(const ReconstructionOutput::Ptr& msg)
- 코드 하 // TODO(nathan) ideally make the copy lighter-weight
// we need to copy over the latest updates to the backend and to LCD
// no fancy threading: we just mark the update time and copy all changes in one go
{ // start critical section
std::unique_lock<std::mutex> lock(state_->backend_graph->mutex);
ScopedTimer merge_timer("frontend/merge_graph", msg->timestamp_ns);
state_->backend_graph->last_update_time = msg->timestamp_ns;
state_->backend_graph->graph->mergeGraph(*dsg_->graph);
} // end critical section
if (state_->lcd_queue) {
// n.b., critical section in this scope!
std::unique_lock<std::mutex> lock(state_->lcd_graph->mutex);
ScopedTimer merge_timer("frontend/merge_lcd_graph", msg->timestamp_ns);
state_->lcd_graph->last_update_time = msg->timestamp_ns;
state_->lcd_graph->graph->mergeGraph(*dsg_->graph);
}
state_->backend_graph
)에 프론트엔드에서 처리한 현재 그래프(dsg_->graph
)를 병합 mergeGraph
함수는 프론트엔드에서 수집된 데이터의 복사본을 유지
하게 되며, 백엔드에서 추가적으로 필요한 정보들을 포함하게 됨
state_->lcd_graph
)가 있는 경우, 동일한 방식으로 LCD 그래프에 프론트엔드 그래프를 병합 mergeGraph
함수는 LCD 그래프에 프론트엔드에서 전달된 최신 그래프 데이터를 병합 backend_input_->mesh_update = last_mesh_update_;
state_->backend_queue.push(backend_input_);
if (state_->lcd_queue) {
state_->lcd_queue->push(lcd_input_);
}
if (logs_) {
// mutex not required because nothing is modifying the graph
frontend_graph_logger_.logGraph(dsg_->graph);
}
if (dsg_->graph && backend_input_) {
ScopedTimer sink_timer("frontend/sinks", msg->timestamp_ns);
Sink::callAll(sinks_, msg->timestamp_ns, *dsg_->graph, *backend_input_);
}
메쉬 업데이트 정보
와 기타 데이터들
을 백엔드와 로컬 루프 클로저로 전달하고, backend_input_
lcd_input_
backend_input_
에 메쉬 업데이트 정보 저장backend_input_->mesh_update = last_mesh_update_;
backend_input_
객체는 백엔드로 전달될 입력 데이터를 담고 있습니다. last_mesh_update_
값을 backend_input_
의 mesh_update
필드에 할당last_mesh_update_
는 이전 메쉬 업데이트 데이터로, backend_queue
에 데이터 푸시state_->backend_queue.push(backend_input_);
backend_queue
는 백엔드 모듈로 전달될 데이터를 저장하는 큐backend_input_
객체를 큐에 푸시(push)하여 백엔드 모듈에서 나중에 해당 데이터를 사용할 수 있도록 함lcd_queue
에 데이터 푸시 (옵션)lcd_queue
는 로컬 루프 클로저(Local Loop Closure, LCD) 큐lcd_input_
객체를 푸시dsg_->graph
와 backend_input_
이 유효한지 확인한 뒤, Sink::callAll()
함수를 통해 모든 등록된 sinks_
콜백 함수를 호출합니다.dsg_->graph
는 현재 그래프 상태, backend_input_
은 백엔드로 전달될 데이터를 포함Sink
는 다양한 모듈들이 이 데이터를 활용하여 추가 작업을 수행할 수 있도록 하는 구조