Warm-up

Zivid 3D 카메라를 Warm-up하고 Thermal Equilibrium(열 평형)에 도달하도록 하면 애플리케이션의 전반적인 정확도와 성공율을 향상시킬 수 있습니다. 이 튜토리얼에서는 Zivid 3D 카메라를 Warm-up하는 이유와 방법을 설명합니다.

SDK v2.7.0부터 Thermal Stabilization 모드를 사용할 수 있습니다. 이 모드를 활성화하면 예열 시간이 단축됩니다.

Why warm-up is needed

Zivid 3D 카메라에는 사용 시 열을 발생시키는 전자 부품(예: 백색광 프로젝터)이 있습니다. 내부 가열로 인해 구성 요소의 온도가 변할 때 기계적 변화가 발생할 수 있습니다.

이러한 기계적 변화는 포인트 클라우드에서 포인트의 위치를 계산할 때 삼각 측량 정확도에 영향을 미치는 필수 광학 구성 요소의 작은 변위를 유발합니다. 카메라의 3D 보정은 warming(가열) 또는 cooling(냉각) 단계에서 정확도가 떨어지는데, 이는 각 내부 구성 요소에서 발생할 수 있는 많은 알 수 없는 온도 상태 때문입니다. 우리는 이 현상을 warm-up drift 라고 부릅니다.

카메라 온도를 제어하고 모든 구성 요소가 일정한 온도(열 평형)에 도달할 수 있도록 충분한 시간을 허용하는 것이 좋습니다. 결과적으로 Zivid 3D 보정은 카메라의 물리적 상태를 인식하고 정확하게 예측하여 정확한 포인트 클라우드를 생성할 수 있습니다.

Temperature change - camera vs. environment

워밍업 테스트에 따르면 Zivid 3D 카메라의 내부 온도는 가능한 가장 빠른 캡처 주기(라이브 모드)에서 최대 1.5°C/min(10분에 15°C)까지 일시적으로 변할 수 있습니다. 보다 일반적인 캡처 주기의 경우, 예를 들어 5초마다 캡처하면 내부 온도 변화가 2~3배 느려집니다(0.5 – 1 °C/min).

반면에 일별 기온은 최대 0.03 °C/min(예: 6시간에 10 °C)까지 변합니다. 이것은 워밍업 중 카메라의 일시적인 온도 변화보다 100배 더 느립니다.

Zivid 3D 카메라에는 주변 온도 변화를 보상할 수 있는 floating calibration이 있어 권장 온도 범위에서 안정성을 보장합니다. Warm-up(예열)되고 적절하게 사용된 카메라는 특정 전체 주변 온도 범위에서 안정적인 성능을 나타냅니다.

Warmup

When to perform warm-up

다음 조건에서 카메라를 Warm-up하는 것이 좋습니다.

  • 애플리케이션에는 다음과 같은 엄격한 허용 오차가 필요합니다.

    • 카메라에서 미터당 거리가 5mm 미만인 피킹 애플리케이션.

    • Inspection applications with < 0.5% trueness error requirements.

  • 응용 프로그램에서 적당한 캡처 주기(10초마다 한 번 이상의 캡쳐)를 요구할 경우.

  • Infield Correction 전.

  • Hand-eye calibration 전.

  • 생산을 실행하기 전에.

  • 카메라를 전원에 연결하지 않은 경우(예: 카메라를 기계적으로 설치한 후).

  • 카메라 전원이 켜져 있지만 지난 20분 동안 포인트 클라우드를 캡처하지 않은 경우(예: 아침에 생산을 시작할 때).

How to perform warm-up

카메라를 Warm-up하려면 고정된 캡처 주기로 10분 동안 3D 포인트 클라우드를 캡처하십시오.

Connect

첫 번째 단계는 카메라에 연결하는 것입니다.

소스로 이동

소스

Zivid::Application zivid;

std::cout << "Connecting to camera" << std::endl;
auto camera = zivid.connectCamera();
소스로 이동

소스

var zivid = new Zivid.NET.Application();

Console.WriteLine("Connecting to camera");
var camera = zivid.ConnectCamera();
소스로 이동

소스

app = zivid.Application()

print("Connecting to camera")
camera = app.connect_camera()

Set Capture cycle and settings

Warm-up 동안 캡처 주기는 애플리케이션의 캡처 주기와 최대한 유사해야 합니다(빈 피킹, 팔레트 제거 등).

배포된 카메라가 예를 들어 5초마다 한 번씩 캡처하는 경우 Warm-up 단계에서 동일한 간격으로 캡처해야 합니다. 카메라에 안정적인 캡처 주기가 없는 경우 Warm-up 단계 중 캡처 주기는 극한 값 사이여야 합니다. 예를 들어 애플리케이션에서 5~11초에 한 번 캡처하는 경우 Warm-up 중에 8초에 한 번 캡처해야 합니다. 응용 프로그램에서 캡처 사이의 지연이 10초보다 길면 카메라를 예열할 필요가 없습니다.

참고

애플리케이션 캡처 주기에 가변 기간이 있는 경우 Thermal Stabilization 모드를 활성화해야 합니다.

Warm-up 중에 사용되는 카메라 설정은 응용 프로그램의 설정과 최대한 유사해야 합니다(사전 구성 또는 Capture Assistant).

소스로 이동

소스

const auto warmupTime = std::chrono::minutes(10);
const auto captureCycle = std::chrono::seconds(5);
const auto maxCaptureTime = std::chrono::milliseconds(1000);

std::cout << "Getting camera settings" << std::endl;
const auto parameters = Zivid::CaptureAssistant::SuggestSettingsParameters{
    Zivid::CaptureAssistant::SuggestSettingsParameters::AmbientLightFrequency::none,
    Zivid::CaptureAssistant::SuggestSettingsParameters::MaxCaptureTime{ maxCaptureTime }
};
const auto settings = Zivid::CaptureAssistant::suggestSettings(camera, parameters);
소스로 이동

소스

var warmupTime = TimeSpan.FromMinutes(10);
var captureCycle = TimeSpan.FromSeconds(5);
var maxCaptureTime = Duration.FromMilliseconds(1000);

Console.WriteLine("Getting camera settings");
var suggestSettingsParameters = new Zivid.NET.CaptureAssistant.SuggestSettingsParameters
{
    MaxCaptureTime = maxCaptureTime,
    AmbientLightFrequency =
        Zivid.NET.CaptureAssistant.SuggestSettingsParameters.AmbientLightFrequencyOption.none
};
var settings = Zivid.NET.CaptureAssistant.Assistant.SuggestSettings(camera, suggestSettingsParameters);
소스로 이동

소스

warmup_time = timedelta(minutes=10)
capture_cycle = timedelta(seconds=user_options.capture_cycle)

if user_options.settings_path:
    print("Loading settings from file")
    settings = zivid.Settings.load(Path(user_options.settings_path))
else:
    print("Getting camera settings from capture assistant")
    suggest_settings_parameters = zivid.capture_assistant.SuggestSettingsParameters(
        max_capture_time=timedelta(milliseconds=1000),
        ambient_light_frequency=zivid.capture_assistant.SuggestSettingsParameters.AmbientLightFrequency.none,
    )
    settings = zivid.capture_assistant.suggest_settings(camera, suggest_settings_parameters)

참고

이 Warm-up 방법은 백색광 프로젝터를 발열체로 사용하여 안정적인 캡처 주기 동안 카메라를 Warm-up 합니다. 총 사이클 시간에 비해 프로젝터가 켜진 시간의 비율을 듀티 사이클이라고 합니다. 듀티 사이클은 예열 단계 후 카메라의 최종 정상 상태 온도뿐만 아니라 카메라가 가열되는 속도에도 영향을 줍니다.

Warm up the camera

카메라를 Warm-up하려면 온도가 안정화될 때까지 10분 동안 계속해서 3D 포인트 클라우드를 캡처합니다.

소스로 이동

소스

std::cout << "Starting warm up for: " << warmupTime.count() << " minutes" << std::endl;

const auto beforeWarmup = SteadyClock::now();

while(SteadyClock::now() - beforeWarmup < warmupTime)
{
    const auto beforeCapture = SteadyClock::now();
    camera.capture(settings);
    const auto afterCapture = SteadyClock::now();
    const auto captureTime = afterCapture - beforeCapture;
    if(captureTime < captureCycle)
    {
        std::this_thread::sleep_for(captureCycle - captureTime);
    }
    else
    {
        std::cout << "Your capture time is longer than your desired capture cycle."
                  << "Please increase the desired capture cycle." << std::endl;
    }

    const auto remainingTime = warmupTime - (SteadyClock::now() - beforeWarmup);

    const auto remainingTimeMinutes = std::chrono::duration_cast<std::chrono::minutes>(remainingTime);
    const auto remainingTimeSeconds =
        std::chrono::duration_cast<std::chrono::seconds>(remainingTime - remainingTimeMinutes);
    std::cout << "Remaining time: " << remainingTimeMinutes.count() << " minutes, "
              << remainingTimeSeconds.count() << " seconds." << std::endl;
}
std::cout << "Warm up completed" << std::endl;
소스로 이동

소스

DateTime beforeWarmup = DateTime.Now;

Console.WriteLine("Starting warm up for: {0} minutes", warmupTime.Minutes);

while (DateTime.Now.Subtract(beforeWarmup) < warmupTime)
{
    var beforeCapture = DateTime.Now;
    camera.Capture(settings);
    var afterCapture = DateTime.Now;

    var captureTime = afterCapture.Subtract(beforeCapture);

    if (captureTime < captureCycle)
    {
        Thread.Sleep(captureCycle.Subtract(captureTime));
    }
    else
    {
        Console.WriteLine(
            "Your capture time is longer than your desired capture cycle. Please increase the desired capture cycle.");
    }
    var remainingTime = warmupTime.Subtract(DateTime.Now.Subtract(beforeWarmup));
    var remainingMinutes = Math.Floor(remainingTime.TotalMinutes);
    var remainingSeconds = Math.Floor(remainingTime.TotalSeconds) % 60;

    Console.WriteLine("Remaining time: {0} minutes, {1} seconds.", remainingMinutes, remainingSeconds);
}

Console.WriteLine("Warm up completed");
소스로 이동

소스

before_warmup = datetime.now()

print(f"Starting warm up for {warmup_time} minutes")
while (datetime.now() - before_warmup) < warmup_time:
    before_capture = datetime.now()
    camera.capture(settings)
    after_capture = datetime.now()

    duration = after_capture - before_capture

    if duration.seconds <= capture_cycle.seconds:
        sleep(capture_cycle.seconds - duration.seconds)
    else:
        print(
            "Your capture time is longer than your desired capture cycle. \
             Please increase the desired capture cycle."
        )

    remaining_time = warmup_time - (datetime.now() - before_warmup)
    remaining_time_minutes = remaining_time.seconds // 60
    remaining_time_seconds = remaining_time.seconds % 60
    print(f"Remaining time: {remaining_time_minutes} minutes, {remaining_time_seconds} seconds.")

print("Warm up completed")

구현 예는 아래의 전체 Warm-up 코드 샘플을 참조하세요.

소스로 이동

소스

/*
Short example of a basic way to warm up the camera with specified time and capture cycle.
*/

#include <Zivid/Zivid.h>

#include <chrono>
#include <iostream>
#include <thread>

using SteadyClock = std::chrono::steady_clock;
using Duration = std::chrono::nanoseconds;

int main()
{
    try
    {
        Zivid::Application zivid;

        std::cout << "Connecting to camera" << std::endl;
        auto camera = zivid.connectCamera();
        const auto warmupTime = std::chrono::minutes(10);
        const auto captureCycle = std::chrono::seconds(5);
        const auto maxCaptureTime = std::chrono::milliseconds(1000);

        std::cout << "Getting camera settings" << std::endl;
        const auto parameters = Zivid::CaptureAssistant::SuggestSettingsParameters{
            Zivid::CaptureAssistant::SuggestSettingsParameters::AmbientLightFrequency::none,
            Zivid::CaptureAssistant::SuggestSettingsParameters::MaxCaptureTime{ maxCaptureTime }
        };
        const auto settings = Zivid::CaptureAssistant::suggestSettings(camera, parameters);
        std::cout << "Starting warm up for: " << warmupTime.count() << " minutes" << std::endl;

        const auto beforeWarmup = SteadyClock::now();

        while(SteadyClock::now() - beforeWarmup < warmupTime)
        {
            const auto beforeCapture = SteadyClock::now();
            camera.capture(settings);
            const auto afterCapture = SteadyClock::now();
            const auto captureTime = afterCapture - beforeCapture;
            if(captureTime < captureCycle)
            {
                std::this_thread::sleep_for(captureCycle - captureTime);
            }
            else
            {
                std::cout << "Your capture time is longer than your desired capture cycle."
                          << "Please increase the desired capture cycle." << std::endl;
            }

            const auto remainingTime = warmupTime - (SteadyClock::now() - beforeWarmup);

            const auto remainingTimeMinutes = std::chrono::duration_cast<std::chrono::minutes>(remainingTime);
            const auto remainingTimeSeconds =
                std::chrono::duration_cast<std::chrono::seconds>(remainingTime - remainingTimeMinutes);
            std::cout << "Remaining time: " << remainingTimeMinutes.count() << " minutes, "
                      << remainingTimeSeconds.count() << " seconds." << std::endl;
        }
        std::cout << "Warm up completed" << std::endl;
    }
    catch(const std::exception &e)
    {
        std::cerr << "Error: " << Zivid::toString(e) << std::endl;
        std::cout << "Press enter to exit." << std::endl;
        std::cin.get();
        return EXIT_FAILURE;
    }

    return EXIT_SUCCESS;
}
소스로 이동

소스

/*
A basic warm-up method for a Zivid camera with specified time and capture cycle.
*/

using System;
using System.Threading;
using Duration = Zivid.NET.Duration;

class Program
{
    static int Main()
    {
        try
        {
            var zivid = new Zivid.NET.Application();

            Console.WriteLine("Connecting to camera");
            var camera = zivid.ConnectCamera();
            var warmupTime = TimeSpan.FromMinutes(10);
            var captureCycle = TimeSpan.FromSeconds(5);
            var maxCaptureTime = Duration.FromMilliseconds(1000);

            Console.WriteLine("Getting camera settings");
            var suggestSettingsParameters = new Zivid.NET.CaptureAssistant.SuggestSettingsParameters
            {
                MaxCaptureTime = maxCaptureTime,
                AmbientLightFrequency =
                    Zivid.NET.CaptureAssistant.SuggestSettingsParameters.AmbientLightFrequencyOption.none
            };
            var settings = Zivid.NET.CaptureAssistant.Assistant.SuggestSettings(camera, suggestSettingsParameters);
            DateTime beforeWarmup = DateTime.Now;

            Console.WriteLine("Starting warm up for: {0} minutes", warmupTime.Minutes);

            while (DateTime.Now.Subtract(beforeWarmup) < warmupTime)
            {
                var beforeCapture = DateTime.Now;
                camera.Capture(settings);
                var afterCapture = DateTime.Now;

                var captureTime = afterCapture.Subtract(beforeCapture);

                if (captureTime < captureCycle)
                {
                    Thread.Sleep(captureCycle.Subtract(captureTime));
                }
                else
                {
                    Console.WriteLine(
                        "Your capture time is longer than your desired capture cycle. Please increase the desired capture cycle.");
                }
                var remainingTime = warmupTime.Subtract(DateTime.Now.Subtract(beforeWarmup));
                var remainingMinutes = Math.Floor(remainingTime.TotalMinutes);
                var remainingSeconds = Math.Floor(remainingTime.TotalSeconds) % 60;

                Console.WriteLine("Remaining time: {0} minutes, {1} seconds.", remainingMinutes, remainingSeconds);
            }

            Console.WriteLine("Warm up completed");
        }
        catch (Exception ex)
        {
            Console.WriteLine("Error: " + ex.Message);
            return 1;
        }
        return 0;
    }
}
소스로 이동

소스

"""
A basic warm-up method for a Zivid camera with specified time and capture cycle.

The sample uses Capture Assistant unless a path to YAML Camera Settings is passed.
"""

import argparse
from datetime import datetime, timedelta
from pathlib import Path
from time import sleep

import zivid


def _options() -> argparse.Namespace:
    """Function to read user arguments.

    Returns:
        Arguments from user

    """
    parser = argparse.ArgumentParser(description=__doc__)

    parser.add_argument(
        "--settings-path",
        required=False,
        help="Path to the YAML file that contains Camera Settings",
    )

    parser.add_argument(
        "--capture-cycle",
        required=False,
        type=float,
        default=5.0,
        help="Capture cycle in seconds",
    )

    return parser.parse_args()


def _main() -> None:
    user_options = _options()
    app = zivid.Application()

    print("Connecting to camera")
    camera = app.connect_camera()
    warmup_time = timedelta(minutes=10)
    capture_cycle = timedelta(seconds=user_options.capture_cycle)

    if user_options.settings_path:
        print("Loading settings from file")
        settings = zivid.Settings.load(Path(user_options.settings_path))
    else:
        print("Getting camera settings from capture assistant")
        suggest_settings_parameters = zivid.capture_assistant.SuggestSettingsParameters(
            max_capture_time=timedelta(milliseconds=1000),
            ambient_light_frequency=zivid.capture_assistant.SuggestSettingsParameters.AmbientLightFrequency.none,
        )
        settings = zivid.capture_assistant.suggest_settings(camera, suggest_settings_parameters)
    before_warmup = datetime.now()

    print(f"Starting warm up for {warmup_time} minutes")
    while (datetime.now() - before_warmup) < warmup_time:
        before_capture = datetime.now()
        camera.capture(settings)
        after_capture = datetime.now()

        duration = after_capture - before_capture

        if duration.seconds <= capture_cycle.seconds:
            sleep(capture_cycle.seconds - duration.seconds)
        else:
            print(
                "Your capture time is longer than your desired capture cycle. \
                 Please increase the desired capture cycle."
            )

        remaining_time = warmup_time - (datetime.now() - before_warmup)
        remaining_time_minutes = remaining_time.seconds // 60
        remaining_time_seconds = remaining_time.seconds % 60
        print(f"Remaining time: {remaining_time_minutes} minutes, {remaining_time_seconds} seconds.")

    print("Warm up completed")


if __name__ == "__main__":
    _main()

카메라를 예열하기 위해 사이클 타임과 카메라 설정 경로를 사용하여 코드 샘플을 실행할 수 있습니다.

Sample: warmup.py

python /path/to/warmup.py --settings-path /path/to/settings.yml --capture-cycle 6.0