19.6.3.2. 전체 활성 인스턴스 순회(Iterating) 및 데이터 병합(Aggregation) 로직
앞선 19.6.3.1 단원에서 우리는 특정 번호(ID)를 하드코딩하여 찌르는 구시대적인 핀셋 거점 타격의 치명적인 한계와 맹점을 뼈저리게 확인했다. PX4 비행 제어기 마스터 데몬이 되려면 우물 안 개구리처럼 “0번 방만 줘“라고 편식해선 안 된다.
진정한 글로벌 센서 하베스터(Harvester) 데몬은 부팅 직후, 그리고 매번 메인 루프가 순환할 때마다 **“현재 이 거대한 마더보드 시스템 안에 vehicle_gps_position이라는 이름표를 단 링 버퍼 방이 총 몇 개나 살아서 활성화(Active)되어 있는가?”**를 OS 커널에게 직접 탐문(orb_group_count)하여 동적으로 그 개수(N)를 알아낸다. 그리고 for 루프를 돌며 0번 방부터 N-1번 방까지 모든 인스턴스 문을 열고 들어가 각 방의 데이터 상태를 싹 다 쓸어 담는(Sweeping) 궁극의 전체 순회(Iteration) 및 병합(Aggregation) 아키텍처를 전개해야만 한다.
1. VFS 인스턴스 전수조사 아키텍처 타설
이 압도적인 멀티플렉싱 코드를 짜기 위해서는, 과거 단일 방만 쳐다보던 _sensor_sub 객체를 std::array나 C 배열(Array) 형태의 집단 컨테이너로 격상시켜 메모리에 배포해야 한다. PX4 C++ 프레임워크는 이를 위해 아주 우아한 컨테이너 래퍼 객체인 uORB::SubscriptionMultiArray (또는 단일 클래스 배열 형태)를 지원한다.
아래의 실전 코드는 최대 3개의 예비 센서까지 지원하는 거대 EKF 데몬이, 부팅 직후와 매 루프마다 모든 인스턴스를 동적으로 싹쓸이하여 데이터를 통합 버퍼에 수집해 내는 무자비한 크롤링(Crawling) 엔진의 코어이다.
#include <uORB/uORB.h>
#include <uORB/topics/sensor_test_data.h>
// 1. [스택의 거대화] 최대 감시 가능한 인스턴스 개수(예: 3개)만큼 C++ Subscription 래퍼 객체 배열을 힙에 타설
uORB::Subscription _sensor_subs[3] = {
{ORB_ID(sensor_test_data), 0}, // 0번 방 감시 전담 포인터
{ORB_ID(sensor_test_data), 1}, // 1번 방 감시 전담 포인터
{ORB_ID(sensor_test_data), 2} // 2번 방 감시 전담 포인터
};
// ... (데몬 메인 루프 내부) ...
void SensorHarvester::Run()
{
// 2. [가장 강력한 동적 탐문] 현재 커널 VFS에 살아서 개통된 sensor_test_data 방(Instance)의 총개수를 런타임 추산!
// 이 값은 센서 하드웨어가 핫플러깅되거나 데몬이 죽을 때마다 1, 2, 3으로 살아서 요동친다.
uint8_t active_instances = orb_group_count(ORB_ID(sensor_test_data));
// 버그 방벽: 배열 최대치(3)를 초과한 생성 에지 케이스 컷오프
if (active_instances > 3) active_instances = 3;
// 3. [전체 순회 융단 폭격] 활성화 확인된 모든 방의 개수만큼 for 루프를 돌며 데이터를 싹쓸이한다.
for (uint8_t i = 0; i < active_instances; i++) {
// 4. 각 i번 째 방에 새로운 데이터가 갱신(Update)되어 비트 플래그가 서 있는지 스캔
if (_sensor_subs[i].updated()) {
// 5. 갱신 확정! i번 파이프라인에서 실제 페이로드 스냅샷을 딥카피 추출
sensor_test_data_s raw_data{};
_sensor_subs[i].copy(&raw_data);
// 6. [데이터 병합 (Aggregation)]
// 방금 i번 센서 보드에서 뽑아낸 이 구조체 데이터를 시스템 글로벌 배열이나 센서 보팅(Voting) 파라미터 매트릭스에 임시 캐싱한다.
// "i번 센서의 측정 온도는 25.4도, 타임스탬프는 1000213"이라는 프로파일이 EKF 블렌더 테이블에 정립된다.
_sensor_data_buffer[i] = raw_data;
PX4_INFO("Polled new data from Instance [%d] -> Vector Aggregation complete.", i);
}
}
// 7. for 루프 폭격 장막이 끝나고 나면, _sensor_data_buffer 배열 안에는
// 현재 살아서 숨 쉬는 모든 1~3개의 센서 데이터 최신 스냅샷이 완벽히 병렬로 모여 있게 된다!
// 나침반 합산 로직(Blending)이나, 최고 품질 센서를 가려내는 투표(Voting) 함수를 바로 이곳에서 때려 버린다.
Do_Sensor_Voting_And_Failover();
}
2. orb_group_count와 for 루프가 만드는 아키텍처의 무결성
이러한 **동적 인스턴스 스캔(orb_group_count)**과 배열 순회(for), 그리고 통합 버퍼 병합(Aggregation) 아키텍처를 도입하는 순간, 당신의 모듈 데몬 코드는 픽스호크 마더보드 하드웨어의 파편화된 스펙 의존성으로부터 완전히 해방된다.
어제까지만 해도 센서가 1개 달린 싸구려 기체에 탑재되었을 때는 알아서 active_instances가 1로 파싱 되어 1번의 루프만 가볍게 돌며 CPU를 소모하지 않는다. 내일 당장 수천만 원짜리 트리플(Triple) 센서 기체에 당신의 모듈을 그대로 복사해서 올리면, 소스 코드 단 1줄의 수정 없이도 알아서 커널 탐문을 통해 개수를 3개로 파싱 해내고 세 곳의 파이프라인을 미친 듯이 병합해 나간다.
이 완벽한 하드웨어 추상화(Hardware Abstraction)와 스케일링 동적 확장성(Dynamic Scalability)이야말로, PX4가 전 세계 모든 잡다한 드론 제조사들의 보드를 통일시켜 버릴 수 있었던 가장 무서운 C++ 소프트웨어 아키텍처의 절대 코어 기술인 것이다.
이제 이렇게 모아놓은 N개의 고품질 데이터 덩어리들을 테이블 위에 올려놓고, **“대체 이 중에서 어떤 놈의 데이터가 가장 오차가 적은 진짜 데이터인가?”**를 심판관처럼 평가하여 살아남을 단 1개의 데이터를 항법에 쑤셔 넣는 센서 투표(Voting)와 장애 조치(Failover) 알고리즘이 19.6.3.3 단원의 마지막 전장으로 우리를 기다리고 있다.