2012-10-17 4 views
0

먼저 달성해야 할 내용을 요약해서 설명하겠습니다. 저는 시간이 지남에 따라 적어도 두 가지 유형의 데이터를받는 수집 시스템을 가지고 있는데이를 국가 추정 프레임 워크에 통합해야합니다.순환 버퍼에서 여러 유형의 시간 순서 이벤트를 큐에 넣으십시오. 조언을주세요.

  1. 유형 : 그것은 (10 Hz에서)하는 FIFO 큐이 충분히 될 것 도착하는대로 일부 데이터를 직접 통합 될 수있는 데이터 수신에 대한 두 가지 시나리오가 있습니다.
  2. 유형 B : 불행히도 데이터의 일부는 더 많은 처리 (1 초)가 필요하므로 지연으로 평가 프레임 워크에 통합됩니다. 이 경우에는 다음을 수행해야합니다. (1) (처리 전) 유형의 수신시 프레임 워크의 이전 상태를 복구하십시오. 다음 (2) 그 시점에서의 상태를 재 계산하는 타입 B에게 데이터를 사용하고 (3)는 (데이터가 존중 인용 된 모든 유형을 그 사이에 수신 데이터를 통합 시간 전진 시간 순서). 뷰의 C++ 프로그래밍 관점에서

, 나는 다음과 같은 해결책을 생각하고 :

  • 은 일반적인 timeSample 클래스를 정의합니다. 따라서 모든 종류의 데이터는 timeSample 어머니 클래스를 상속 한 클래스로 캡슐화됩니다. 따라서 포인터 timeSample에서 동적으로 캐스팅 할 수있는 timeSampleAtimeSampleB을 갖습니다. 이것은 샘플이 현재 샘플 일 수 있고 적절한 함수를 호출 할 수 있기 때문에 샘플을 평가 프레임 워크로 다시 전달할 때 유용합니다.
  • 각 timeSample 하위 클래스에는 순환 버퍼가 있습니다. 그래서 timeSampleA 데이터는 circularBuffer<timeSampleA>에 저장되고, timeSampleB 데이터는 circularBuffer<timeSampleB>에 저장됩니다.
  • multiset<timeSample*>은 샘플의 시간 순서화 된 포인터를 저장하는 데 사용됩니다 (포인터 중 일부는 circularBuffer<timeSampleA> 내부의 데이터를 가리키고 다른 일부는 circularBuffer<timeSampleB> 내부의 데이터를 가리킴). timeSample 포인터는 샘플이 수신 된 시간을 저장하는 timeSample 인스턴스 내부의 시간 필드를 사용하여 정렬됩니다.
  • 데이터가 올바르게 관리되도록 모든 컨테이너가 동일한 클래스에 포함됩니다. 예를 들어, 유형 B 샘플이 처리를 완료하고 평가가 갱신되면; 어느 샘플을 지울 수 있는지를 정의하는 컷오프 시간이 증가합니다. 이 작업을 수행하려면 multisetcircularBuffer에서 데이터를 올바르게 지울 필요가 있습니다.

내가 알고 싶습니다 :

귀하의 의견을 환영합니다!

+0

지금까지 무엇을 작성 했습니까? – Raedwald

+0

멀티 세트 작업을 시작했습니다. 자동으로 정렬되는'timeSample'을 추가 할 수 있습니다. typeB 샘플을 "사용"할 때 해당 typeA 및 typeB 샘플을 삭제하는 차단 시간을 앞당길 수 있습니다. – jespestana

+0

저는 약간의 불명확합니다 - 센서 측의 "처리 시간"입니다 (따라서 B 형 샘플을 1 회 체납합니다), 또는 B 형 샘플을 현재 상태에 통합하는 데 필요한 시간입니까 (그래서 type B 샘플은 정시에 도착하지만 즉시 상태로 통합 될 수는 없습니까?) –

답변

1

나는 당신이 일을 조금 단순화 할 수 있다고 생각 :

좋은 새로운 그러기 부스트 lib 디렉토리가 있습니다.

나는 의견에서 묻는 불확실성이있다. 유형 B 샘플이 체납에 도착하는 경우 "X"를 지정하고, 유형 B 샘플은 시간에 도착하지만 상태로 통합하는 경우 "Y"를 지정합니다.

  • 는 두 개의 원형 버퍼를 유지하지만, 각 샘플과 관련된 타임 스탬프가 확실하게 - 샘플 또는 CircularBuffer<pair<timeSampleA, timestamp_t>>에 버퍼를 변경하여 하나가. X의 경우, 이것은 데이터 샘플이 원래 측정 된 시간 (즉, 귀하의 주에 통합되어야하는 공칭 시간)이어야합니다. 두 종류의 샘플이 제 시간에 도착하는 Y의 경우, 샘플을 수신하면 시간 소인을 찍을 수도 있습니다.
  • 멀티 세트를 잃습니다. 멀티 세트를 잃었으므로 원하는 경우 동적 다형성을 잃을 수도 있습니다.
  • 은 시스템에 대한 두 가지 상태, 즉 "정확함"과 "부정확 한"상태를 유지합니다.
  • 유형 A 샘플이 도착하면이를 A 버퍼에 추가하십시오. 가능한 한 빨리 A 버퍼의 샘플을 부정확 한 상태에 적용합니다 (A 버퍼의 위치를 ​​추적하여 부정확 한 상태로 통합 된 것을 나타낼 수 있으며 메시지 도착을 서비스 한 후 두 번째로 우선 순위가 높은 작업은 다음과 같습니다). 이 위치를 앞으로 옮기십시오).
  • 유형 B 샘플이 도착하면 B 버퍼에 추가하십시오.
  • "부정확 한"상태를 업데이트하는 즉시 두 버퍼의 샘플을 "정확한"상태로 적용하십시오. 개별적으로 주문 된 두 개의 컨테이너가 있기 때문에 순서대로 단일 컨테이너가 필요하지 않습니다. 따라서 실제로는 양방향 병합을 수행 할 수 있습니다. 즉, 각 버퍼에서 가장 오래된 샘플의 타임 스탬프를 비교하고 어느 것이 더 오래되었는지를 처리합니다. 샘플을 정확한 상태로 적용 할 때 버퍼에서 샘플을 제거하십시오. X의 경우, 유형 A 샘플이 대기열의 가장 최근 유형 B 샘플보다 최신 인 경우 정확한 상태로 적용하지 마십시오. 그보다 최근 인 경우 보다 최신일 수 있기 때문입니다 다음 유형 B 샘플을 받으십시오.

"정확한"상태를 복사하고 부정확 한 상태의 A 버퍼 위치를 A 버퍼의 시작으로 다시 설정 한 다음 언제든지 "잘못된"상태를 새로 고칠 수 있습니다 가능한 빨리 A 버퍼를 부정확 한 상태로 만듭니다. 일단 그 위치가 어디로 옮겼 으면 그 위치는 그 정확도가 전보다 더 엄격합니다. 유형 B 샘플이 정확한 상태로 통합 될 때마다 이것을 수행하는 것이 합리적 일 수 있지만, 이론적으로 덜 자주 수행 할 수 있습니다.

고정 버퍼 크기가 결코 초과되지 않는다는 가정하에 요소를 추가 할 때 순환 버퍼가 메모리 할당을 피하고 충돌을 줄이기 위해 효과적이라는 것에 유의하십시오. 큐잉 이론은 얼마나 자주 발생하는지 결정하는 데 있습니다. 소요 시간을 두려워하지 않으면 FIFO 큐로 deque을 사용할 수 있습니다. 그러나 이는 실시간 요구 사항이 무엇인지에 달려 있습니다. 새로운 정보를 정기적으로 통합 후

+0

원형 버퍼가 필요 없다고 생각합니다. A와 B를 모두 저장하는 간단한 FIFO가 충분해야합니다. 데이터 A는 즉시 "빠른 상태"로 통합됩니다. 다른 스레드는 FIFO의 모든 데이터를 "느린 상태"로 도착한 순서대로 대기열에서 제거하고 통합합니다. 큐를 비울 때마다 "빠른"상태를 덮어 씁니다. – Offirmo

+1

@Offirmo : 성능 차이가 문제가되지 않는다면, 버퍼가 원형이든 선형이든 세부적인 사항이므로, 귀찮은 것을 저장하고'deque '를 사용하십시오. 내가 "사례 X"라고 부르는 것에서, 대기열은 결코 비어 있지 않을 수도 있습니다. 왜냐하면'B' 표본이 도착한 후에 상태로 병합하는데 걸린 시간이'A의 도착 빈도보다 큽니다 '샘플. 그래서 나는 샘플이 도착할 때까지 더 많이 알기 전까지는 일반적인 상태를 유지하려고 노력했으며 느린/정확한 상태에서 복제하는 것보다 빠르고/부정확 한 상태를 재 계산할 수있는 기능을 유지합니다. –

+0

사실 우리는 데이터 수신의 타임 스탬프를 알 수 있도록 "사례 Y"로 작업하고 있습니다. 두 가지 유형의 데이터 만 넣었지만 더 많은 유형을 고려하여 다른 이벤트를 고려할 수 있습니다 (예 : 엔진 끄기 또는 탐색 모드 변경). 어쨌든, 우리의 경우 유형 A 샘플은 유형 B 샘플보다 높은 획득 주파수 (10-20Hz)를가집니다 (유효 속도 처리는 1-2Hz입니다). – jespestana

1

결과가 완전하지 않더라도 새로운 데이터가 도착하면 실제로 결과를 업데이트해야합니까?

원자로 패턴을 완전히 사용해야합니다.

먼저 모든 이벤트가 도착하자 마자 외우고 빠른 FIFO에 저장합니다. 현재 처리 중이며, "할일"FIFO에 추가하십시오.

그런 다음 작업자 스레드는 동일한 순서 또는 도착으로 FIFO를 depile 처리하고 필요에 따라 1 초를 사용하여 처리 속도를 자체 처리합니다.

스레드를 가질 수 없으면 작은 조각으로 처리를 분할하여 두 개의 처리 조각 사이에서 FIFO에 새 데이터를 추가하는 데 시간이 걸릴 수 있습니다. http://www.boost.org/doc/libs/1_40_0/doc/html/boost_asio/overview/core/async.html (아직 사용하지하지만 난에 계획 않음)

+0

* 불완전한 경우에도 새로운 결과가 도착하자마자 실제로 결과를 업데이트해야합니까? * 예. 나는 상태 추정을 사용하여 차량을 제어한다. typeB (처리 후) 측정 값은 더 정확하며 데이터를 사용하는 올바른 방법은 추정 프레임 워크의 상태를 typeB 측정의 수신 (처리 전)으로 복원하는 것입니다. 나는 원자로 패턴을 살펴볼 것이다. 감사! – jespestana

+0

그것은 실제로 요구 사항입니다.당신 문제는 흥미 롭습니다. – Offirmo

1

두 번째 시도 : 도착시

  • 모든 데이터 (A와 B)는 간단한 FIFO에 저장됩니다.
  • 두 상태가 동시에 유지됩니다 : "fast_but_inaccurate"및 "slow_but_precise".
  • 데이터 A는 FIFO에 대기중인 동시에 도착한 즉시 즉시 "빠른 상태"로 통합됩니다.
  • 데이터 B는 FIFO에 도착할 때만 대기합니다.
  • 또 다른 스레드는 FIFO에서 A와 B를 모두 삭제 한 것과 동일한 순서로 큐에서 제거하고 "느린 상태"로 통합합니다. 스레드가 FIFO를 비울 때마다 "느린"상태에서 "빠른"상태를 덮어 씁니다.

등등.

참고 : "worker thread + enqueue thread"라고 말하면 이러한 임베디드 시스템이있는 경우 "메인 처리 + 인터럽트"가 될 수도 있습니다. 솔루션은 두 경우 모두 작동합니다.

+0

동료 근로자와 문제를 논의했습니다. 효율성을 높이기 위해 timeSample 객체 (포인터가 아님)를 저장하는 일정한 크기의 circularBuffer로 작업하고 싶습니다. 하나의 컨테이너에 다른 유형의 샘플 (다른 sizeof() 바이트)의 객체를 저장하려면 데이터를 char []로 직렬화하고 직렬화 및 직렬화를 올바르게 구현해야한다고 생각합니다. 우리는 예상되는 획득 속도로 "일정한"크기를 조정하는 데이터의 종류마다 하나의 circularBuffer를 갖는 것이 더 낫다고 믿습니다. 우리는 정말로 당신의 의견을 알고 싶어합니다! – jespestana

+0

우리는 완전히 동의합니다. FIFO를 원형 버퍼로 구현하는 것이 좋으며 직렬화 메커니즘을 사용하여이 버퍼에 데이터를 저장하는 것이 좋습니다. 나는 두 개의 다른 버퍼에 데이터 A와 B를 저장하는 것을 좋아하지 않는다. 왜냐하면 그 순서를 풀고 날짜를 저장해야하고 나중에 이벤트를 재정렬하기 위해 날짜 비교를해야하기 때문이다. 하지만 당신의 크기 문제를 이해합니다. 그래서 나는 두 번째 순환 버퍼에 저장된 여분의 B 데이터를 사용하여 A와 부분 B (B 데이터가 더 큼)를 저장하는 첫 번째 순환 버퍼를 갖게됩니다. – Offirmo

+0

반면에, 내가 생각할 때, 날짜 비교는 어렵지 않습니다 (큐를 풀 때 두 버퍼에서 가장 오래된 레코드를 선택하십시오). 그리고 B 데이터를 두 부분으로 나누는 것은 더 복잡 할 수 있습니다. 그래서 저는 네가 동료와 함께 찾은 해결책이 최고라고 생각합니다. 우리 모두 좋은 팀워크! – Offirmo