You're viewing an old version of the documentation. Click here to see the latest release.

预热

对Zivid 3D相机进行预热并达到热平衡,可以提高应用的整体准确性和成功率。在本文中,我们会解释为什么以及预热如何对Zivid 3D相机进行预热。

小技巧

从SDK v2.7.0开始,添加了一 个 热稳定功能 模式。启用此模式后,预热时间将会缩短。

为什么需要预热

Zivid 3D相机具有在使用时会产生热量的有源电子元件(例如白光投影仪)。内部发热会导致组件在温度变化时发生机械变化。

这些机械变化会导致基本光学组件发生微小的位移,从而在计算点云中点的位置时影响三角测量精度。由于每个内部组件可能处于许多未知的可能温度状态,因此相机的3D标定在加热或冷却阶段会不太准确。我们称这种现象为*预热漂移*。

建议控制相机温度并留出足够的时间让所有组件达到稳定的温度(热平衡)。因此,Zivid 3D标定可以识别并准确预测相机的物理状态并生成正确的点云。

预热

何时进行热身

建议在以下情况下预热相机:

  • 对误差要求很严格的应用,例如:

    • 对于小于5毫米/距相机1米距离的抓取应用。

    • 小于0.5%真实度误差要求的检测应用。

  • 达到中等捕获周期(快于每10秒捕获一次)的应用。

  • 在现场标定之前。

  • 在手眼标定之前。

  • 在运行生产之前。

  • 相机还未连接到电源时,例如安装相机后。

  • 当相机已开机但在过去20分钟内未捕获点云时,例如早上启动生产单元时。

如何进行预热

要预热相机,请以固定的捕获周期捕获3D点云10分钟。

连接

第一步是连接相机。

Zivid::Application zivid;

std::cout << "Connecting to camera" << std::endl;
auto camera = zivid.connectCamera();

设定捕获周期和设置

在预热期间,捕获周期应尽可能与实际应用中的捕获周期相似(料箱拾取、卸垛等)。

如果部署的相机每5秒进行一次捕获,它应该在预热阶段以相同的间隔进行捕获。如果生产中的相机没有稳定的捕获周期,那么预热阶段的捕获周期应该在极值之间,例如,如果它在实际应用中每5到11秒捕获一次,则应该在预热时每8秒捕获一次。如果实际应用中捕获之间的间隔超过10秒,则无需预热相机。

备注

如果捕获周期是变化的,则应启 用 热稳定功能 模式。

预热期间使用的相机设置也应尽可能与实际应用中的设置相似(预配置或捕获助手)。

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);

备注

这种预热方法使用白光投影仪作为加热元件,在稳定的捕获周期中预热相机。投影仪开启时间与总循环时间的比率称为占空比。占空比会影响相机加热的速率以及相机在预热阶段之后的最终稳态温度。

预热相机

要预热相机,请循环捕获3D点云10分钟,直到温度稳定。

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

const auto beforeWarmup = HighResClock::now();

while(HighResClock::now() - beforeWarmup < warmupTime)
{
    const auto beforeCapture = HighResClock::now();
    camera.capture(settings);
    const auto afterCapture = HighResClock::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 - (HighResClock::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;

有关实现的示例,请参阅下面的完整预热代码示例。

/*
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 HighResClock = std::chrono::high_resolution_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 = HighResClock::now();

        while(HighResClock::now() - beforeWarmup < warmupTime)
        {
            const auto beforeCapture = HighResClock::now();
            camera.capture(settings);
            const auto afterCapture = HighResClock::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 - (HighResClock::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;
}