void FrontendModule::updatePoseGraph(const ReconstructionOutput& input) {
if (!tracker_) {
LOG_FIRST_N(WARNING, 1)
<< "PoseGraphTracker disabled, no agent layer will be created";
return;
}
std::unique_lock<std::mutex> lock(dsg_->mutex);
ScopedTimer timer("frontend/update_posegraph", input.timestamp_ns);
const auto& prefix = GlobalInfo::instance().getRobotPrefix();
const auto& agents = dsg_->graph->getLayer(DsgLayers::AGENTS, prefix.key);
if (lcd_input_) {
lcd_input_->new_agent_nodes.clear();
}
const auto packet = tracker_->update(input.timestamp_ns, input.world_T_body());
if (backend_input_) {
backend_input_->agent_updates = packet;
}
for (const auto& pose_graph : packet.pose_graphs) {
if (!pose_graph || pose_graph->nodes.empty()) {
continue;
}
for (const auto& node : pose_graph->nodes) {
if (node.key < agents.numNodes()) {
continue;
}
Eigen::Vector3d position = node.pose.translation();
Eigen::Quaterniond rotation(node.pose.linear());
// TODO(nathan) implicit assumption that pgmo ids are sequential starting at 0
// TODO(nathan) implicit assumption that gtsam symbol and dsg node symbol are
// same
NodeSymbol pgmo_key(prefix.key, node.key);
const std::chrono::nanoseconds stamp(node.stamp_ns);
VLOG(5) << "[Hydra Frontend] Adding agent " << agents.nodes().size() << " @ "
<< stamp.count() << " [ns] for layer " << agents.prefix.str()
<< " (key: " << node.key << ")";
auto attrs = std::make_unique<AgentNodeAttributes>(rotation, position, pgmo_key);
if (!dsg_->graph->emplaceNode(
agents.id, agents.prefix, stamp, std::move(attrs))) {
VLOG(1) << "[Hydra Frontend] repeated timestamp " << stamp.count()
<< "[ns] found";
continue;
}
// TODO(nathan) save key association for lcd
const size_t last_index = agents.nodes().size() - 1;
agent_key_map_[pgmo_key] = last_index;
if (lcd_input_) {
lcd_input_->new_agent_nodes.push_back(agents.prefix.makeId(last_index));
}
}
}
addPlaceAgentEdges(input.timestamp_ns);
assignBowVectors(agents);
}
갱신된 포즈 그래프를 포함한 PoseGraphPacket 형태를 반환
하여 lcd_input_
(new_agent_nodes 맴버 변수)에 추가addPlaceAgentEdges
assignBowVectors
특정 단어 ID
와 해당 단어의 가중치
로 구성AGENTS
)를 찾습니다.lcd_input_
)이 활성화된 경우, const auto packet = tracker_->update(input.timestamp_ns, input.world_T_body());
tracker_->update()
호출을 통해 로봇의 현재 포즈를 업데이트
pose_graphs
)를 갱신packet
에 있는 포즈 그래프를 백엔드(backend_input_
)로 전달pose_graphs
) 내 각 노드를 순회하며 에이전트 노드를 추가key
가 기존 노드 수보다 작다면 이미 존재하는 노드로 간주하고 건너뜁니다.translation
)와 회전(rotation
)을 Eigen 형식으로 변환합니다.pgmo_key
를 생성해 해당 노드의 키를 관리 AgentNodeAttributes
객체로 에이전트 노드 속성을 설정하고, DSG 그래프에 노드를 추가agent_key_map_
에 노드의 키와 인덱스를 저장합니다. lcd_input_
에 기록struct LcdInput {
using Ptr = std::shared_ptr<LcdInput>;
uint64_t timestamp_ns;
NodeIdSet archived_places;
std::vector<NodeId> new_agent_nodes;
};
addPlaceAgentEdges()
함수를 호출해 장소 노드와 에이전트 간의 연결을 추가assignBowVectors()
를 호출해 에이전트에 Bag-of-Words(BOW) 벡터를 할당assignBowVectors
함수의 알고리즘 및 로직 심층 분석특징점 기반의 환경 인식(인코딩 벡터)
)특정 단어 ID
와 해당 단어의 가중치
로 구성cached_bow_messages_
에 저장agent_key_map_
에서 찾아 해당 노드를 식별합니다.