Multithreading

이 튜토리얼은 다중 스레드에서 Zivid 카메라를 안전하게 작동하는 방법을 보여줍니다. 다음 예제에서는 하나의 스레드에서 카메라의 상태를 지속적으로 폴링하는 동시에 다른 스레드에서 동일한 카메라로 캡처를 대기열에 추가합니다.

참고

Zivid SDK는 SDK 2.9부터 동시에 여러 스레드에서 동일한 카메라를 작동하는 것을 지원합니다.

먼저 서로 다른 캡처를 구별하기 위해 서로 다른 설정을 만듭니다. 서로 다른 노출 시간을 사용하여 투사된 패턴을 관찰하여 캡처 간의 차이를 쉽게 알아차릴 수 있습니다.

std::cout << " Creating different settings to distinguish between different captures" << std::endl;
const auto settings0 =
    Zivid::Settings{ Zivid::Settings::Engine::phase,
                     Zivid::Settings::Acquisitions{ Zivid::Settings::Acquisition{
                         Zivid::Settings::Acquisition::Aperture{ 5.66 },
                         Zivid::Settings::Acquisition::Gain{ 1.0 },
                         Zivid::Settings::Acquisition::ExposureTime{ std::chrono::microseconds{ 10000 } } } } };
const auto settings1 = Zivid::Settings{ Zivid::Settings::Acquisitions{ settings0.acquisitions().at(0).copyWith(
    Zivid::Settings::Acquisition::ExposureTime{ std::chrono::microseconds{ 30000 } }) } };
const auto settings2 = Zivid::Settings{ Zivid::Settings::Acquisitions{ settings0.acquisitions().at(0).copyWith(
    Zivid::Settings::Acquisition::ExposureTime{ std::chrono::microseconds{ 90000 } }) } };

그런 다음 카메라 상태를 지속적으로 확인하는 스레드를 실행합니다.

pollingThreads.emplace_back(std::async(std::launch::async, [&]() {
    while(!stop)
    {
        const auto state = camera.state();
        std::cout << "Camera: " << camera.info().serialNumber() << std::endl;
        std::cout << state << std::endl;
        std::this_thread::sleep_for(std::chrono::milliseconds(5000));
    }
}));

마지막으로, 각 스레드에서 서로 다른 설정을 사용하여 3개의 다른 스레드를 회전시켜 3개의 캡처를 대기열에 추가합니다.

const auto frame0 = std::async(std::launch::async, [&]() { return camera.capture(settings0); });
const auto frame1 = std::async(std::launch::async, [&]() { return camera.capture(settings1); });
const auto frame2 = std::async(std::launch::async, [&]() { return camera.capture(settings2); });

보시다시피 다른 스레드에서 동일한 카메라를 작동하는 것은 간단합니다. 그러나 프로그램의 안전한 동작을 보장하기 위해 피해야 하는 특정 API 및 상황에는 몇 가지 제한 사항이 있습니다.

다음 API를 호출함과 동시에 카메라를 작동해서는 안 됩니다.

  • Zivid::Application::cameras()

  • Zivid::Camera::connect()

  • Zivid::Firmware::update()

여러 스레드에서 동시에 위의 API 조합을 호출하는 경우에도 마찬가지입니다.

여러 대의 Zivid 카메라를 사용할 때 카메라를 나열하고 SDK를 통해 카메라에 순차적으로 연결하는 것이 중요합니다.

std::cout << "Finding cameras" << std::endl;
auto cameras = zivid.cameras();
std::cout << "Number of cameras found: " << cameras.size() << std::endl;

// It is important to connect to cameras sequentially
for(auto &camera : cameras)
{
    std::cout << "Connecting to camera: " << camera.info().serialNumber().value() << std::endl;
    camera.connect();
}

하나의 스레드에서 모든 카메라에 연결한 다음 카메라를 제어하는 새 스레드를 생성하는 것이 좋습니다(여러 스레드에서 동일한 카메라를 동시에 “use” 하는 것은 thread safe 입니다).