MeshSegmenter
는 3D 메쉬 데이터를 기반으로 특정 라벨에 대한 객체 클러스터를 탐지하고, 이를 동적 씬 그래프(DSG)에 반영하는 모듈detect
함수: 메쉬에서 객체를 감지하는 역할.updateGraph
함수: 감지된 객체 클러스터를 DSG에 업데이트하거나, 새로운 노드를 추가mergeActiveNodes
함수: 비슷한 객체 노드를 병합.getActiveNodes
함수: 현재 활성화된 노드의 ID를 반환.updateNodeInGraph
함수: 기존 노드를 업데이트.addNodeToGraph
함수: 새로운 노드를 DSG에 추가.각 구성 요소에 대한 로직을 자세히 설명합니다.
MeshSegmenter::detect
LabelClusters MeshSegmenter::detect(uint64_t timestamp_ns,
const kimera_pgmo::MeshDelta& delta,
const std::optional<Eigen::Vector3d>& pos) {}
detect
함수는 메쉬 데이터를 기반으로 특정 라벨에 해당하는 클러스터를 탐지하는 역할getActiveIndices
)const auto indices = getActiveIndices(delta, pos, config.active_index_horizon_m);
getActiveIndices()
함수를 사용하여 활성화된 메쉬 포인트의 인덱스를 가져옵니다.delta
: 메쉬의 변화(delta) 정보를 담고 있으며, 이는 현재 탐지하려는 메쉬 데이터를 나타냄pos
: 탐지 범위의 중심점입니다. 만약 이 값이 존재하면, 그 주변에 있는 메쉬 포인트들을 활성화된 인덱스로 간주합니다.config.active_index_horizon_m
: 탐지 범위를 나타냅니다. pos
가 주어지면, 이 범위 내에 있는 포인트들만 활성화된 인덱스로 처리indices
는 활성화된 메쉬 포인트들의 인덱스 리스트이며, 나중에 클러스터링에 사용getLabelIndices
)const auto label_indices = getLabelIndices(config, delta, indices);
getLabelIndices()
함수를 통해, 활성화된 인덱스 중에서 라벨에 해당하는 메쉬 포인트들을 필터링delta
: 메쉬 데이터의 변화 정보로, 각 메쉬 포인트가 어떤 라벨(semantic label)을 가지고 있는지 정보를 포함indices
: 활성화된 메쉬 인덱스 목록config.labels
: 감지하려는 대상 라벨들의 리스트입니다. 예를 들어, 자동차, 사람 등 특정 객체 라벨에 해당하는 포인트들만 감지label_indices
는 각 라벨별로 활성화된 메쉬 포인트들의 인덱스를 저장한 사전(딕셔너리) 형태for (const auto label : config.labels) {
if (!label_indices.count(label)) {
continue;
}
if (label_indices.at(label).size() < config.min_cluster_size) {
continue;
}
const auto clusters = findClusters(config, delta, label_indices.at(label));
VLOG(2) << "[Mesh Segmenter] - Found " << clusters.size()
<< " cluster(s) of label " << static_cast<int>(label);
label_clusters.insert({label, clusters});
}
config.labels
)을 순회하며, 라벨에 해당하는 메쉬 포인트들을 클러스터링config.min_cluster_size
(최소 클러스터 크기)보다 작다면, 해당 라벨에 대한 클러스터링을 수행하지 않고 건너뜁니다.findClusters()
함수를 호출하여 해당 라벨에 대한 메쉬 포인트들로 클러스터를 생성label_clusters
라는 사전에 라벨별로 저장됩니다. MeshSegmenter::updateGraph
함수void MeshSegmenter::updateGraph(uint64_t timestamp_ns,
const LabelClusters& clusters,
size_t num_archived_vertices,
DynamicSceneGraph& graph) {}
탐지된 클러스터들에 대해 순회하며 처리
archiveOldNodes
)archiveOldNodes(graph, num_archived_vertices);
archiveOldNodes()
함수는 그래프의 이전 노드들 중에서 더 이상 활성화되지 않은 노드를 아카이브 처리graph
: 현재 동적 씬 그래프num_archived_vertices
: 이 값은 아카이브 처리 기준을 결정하며, for (auto&& [label, clusters_for_label] : clusters) {
clusters
는 라벨별로 탐지된 클러스터들을 저장한 구조label
: 각 클러스터에 해당하는 라벨을 나타냅니다.clusters_for_label
: 해당 라벨에 속하는 클러스터들의 리스트 for (const auto& cluster : clusters_for_label) {
bool matches_prev_node = false;
std::vector<NodeId> nodes_not_in_graph;
for (const auto& prev_node_id : active_nodes_.at(label)) {
const auto& prev_node = graph.getNode(prev_node_id);
if (nodesMatch(cluster, prev_node)) {
updateNodeInGraph(graph, cluster, prev_node, timestamp_ns);
matches_prev_node = true;
break;
}
}
active_nodes_.at(label)
를 통해 해당 라벨에 해당하는 이전에 추가된 노드들을 가져옵니다.nodesMatch()
함수를 사용해 클러스터와 노드가 일치하는지 확인nodesMatch()
함수는 updateNodeInGraph(graph, cluster, prev_node, timestamp_ns)
함수를 호출해, 기존 노드의 메쉬 포인트 연결 및 기타 속성들을 갱신
matches_prev_node
를 true
로 설정하고, 더 이상의 검사를 중단합니다(break
).if (!matches_prev_node) {
addNodeToGraph(graph, cluster, label, timestamp_ns);
}
addNodeToGraph()
함수는 새로운 노드를 생성하고, 해당 클러스터와 라벨, 그리고 현재 타임스탬프를 기반으로 그래프에 추가mergeActiveNodes
)mergeActiveNodes(graph, label);
mergeActiveNodes()
함수를 통해 병합됩니다.void MeshSegmenter::archiveOldNodes(const DynamicSceneGraph& graph,
size_t num_archived_vertices) {}
더 이상 활성 상태로 유지되지 않는 오래된 노드들
을 아카이브(제거)하는 역할for (const auto& label : config.labels) {
config.labels
: 그래프에서 관리 중인 라벨 목록for (const auto& node_id : active_nodes_.at(label)) {
active_nodes_.at(label)
은 해당 라벨에 속하는 활성 노드들의 집합if (!graph.hasNode(node_id)) {
removed_nodes.push_back(node_id);
continue;
}
auto& attrs = graph.getNode(node_id).attributes<ObjectNodeAttributes>();
ObjectNodeAttributes
는 노드가 가지고 있는 속성으로, bool is_active = false;
for (const auto index : attrs.mesh_connections) {
if (index >= num_archived_vertices) {
is_active = true;
break;
}
}
attrs.mesh_connections
: 이 노드가 연결된 메쉬 포인트의 인덱스 목록num_archived_vertices
보다 크면, 해당 노드는 여전히 활성화된 상태num_archived_vertices
는 아카이브된 메쉬 포인트의 수를 나타냅니다. attrs.is_active = is_active;
if (!attrs.is_active) {
removed_nodes.push_back(node_id);
}
is_active
값에 따라 노드의 활성 상태를 업데이트합니다.attrs.is_active = is_active;
: is_active
값을 노드 속성의 활성 상태에 적용합니다.for (const auto& node_id : removed_nodes) {
active_nodes_[label].erase(node_id);
}
active_nodes_
에서 제거합니다.active_nodes_[label].erase(node_id)
: 해당 라벨에 속한 활성 노드 목록에서, 제거할 노드들을 삭제합니다.