diff --git a/README.md b/README.md index 0b35a72a..45817420 100644 --- a/README.md +++ b/README.md @@ -177,7 +177,7 @@ from the camera can be used. CUDA device using OpenCV. - [CaptureAndConvertToDlpackTensorOnCuda] - Capture a 2D+3D frame with the Zivid SDK and build DLPack tensors directly from the - Zivid DeviceArrays on the CUDA device. + Zivid DeviceArrays on the CUDA - **Transform** - [TransformPointCloudFromMillimetersToMeters] - Transform point cloud data from millimeters to meters. @@ -329,7 +329,7 @@ The following HALCON versions have been tested and confirmed to work with Zivid cameras: - 19.05 Progress, 20.05 Progress, 21.11 Progress, 24.05 Progress, 24.11 - Progress-Steady, 25.05 Progress + Progress-Steady, 25.05 Progress, 25.11 Progress, 26.05 Progress We recommend using one of the HALCON versions we have tested. diff --git a/source/Applications/Advanced/Visualization/CaptureVis3DInLoop/CaptureVis3DInLoop.cpp b/source/Applications/Advanced/Visualization/CaptureVis3DInLoop/CaptureVis3DInLoop.cpp index e6a5289b..9f3bf093 100644 --- a/source/Applications/Advanced/Visualization/CaptureVis3DInLoop/CaptureVis3DInLoop.cpp +++ b/source/Applications/Advanced/Visualization/CaptureVis3DInLoop/CaptureVis3DInLoop.cpp @@ -5,7 +5,8 @@ Capture point clouds, with color, from the Zivid camera, and visualize them in a #include #include -#include +#include +#include #include #include @@ -26,49 +27,48 @@ int main() Zivid::Settings2D::Acquisitions{ Zivid::Settings2D::Acquisition{} } } } }; std::cout << "Capturing frame" << std::endl; - auto frame = camera.capture2D3D(settings); + const auto frame = camera.capture2D3D(settings); std::cout << "Settings:" << frame.settings() << std::endl; std::cout << "Setting up visualization" << std::endl; - std::atomic_bool visualizerRunning{ false }; - auto visualizerPromise = std::promise(); - auto visualizerFuture = visualizerPromise.get_future(); + auto visualizer = Zivid::Visualization::Visualizer(); - std::thread visualizationThread([&frame, &visualizerPromise, &visualizerRunning]() { - auto visualizer = Zivid::Visualization::Visualizer(); + std::cout << "Visualizing point cloud" << std::endl; + visualizer.showMaximized(); + visualizer.show(frame); + visualizer.resetToFit(); - // Pass the visualizer to the main thread - visualizerPromise.set_value(&visualizer); + std::atomic_bool visualizerRunning{ true }; + std::exception_ptr captureException; - std::cout << "Visualizing point cloud" << std::endl; - visualizer.showMaximized(); - visualizer.show(frame); - visualizer.resetToFit(); - - std::cout << "Running visualizer. Blocking until window closes." << std::endl; - visualizerRunning = true; - visualizer.run(); - visualizerRunning = false; + std::thread captureThread([&camera, &settings, &visualizer, &visualizerRunning, &captureException]() { + try + { + while(visualizerRunning) + { + const auto newFrame = camera.capture2D3D(settings); + if(visualizerRunning) + { + visualizer.show(newFrame); + } + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + } + } + catch(...) + { + captureException = std::current_exception(); + visualizer.close(); + } }); - // Get the visualizer handle in the main thread - auto visualizerHandle = visualizerFuture.get(); - - while(!visualizerRunning) - { - std::this_thread::sleep_for(std::chrono::milliseconds(1)); - } - while(visualizerRunning) + std::cout << "Running visualizer. Blocking until window closes." << std::endl; + visualizer.run(); + visualizerRunning = false; + captureThread.join(); + if(captureException) { - frame = camera.capture2D3D(settings); - if(!visualizerRunning) - { - break; - } - visualizerHandle->show(frame); - std::this_thread::sleep_for(std::chrono::milliseconds(10)); + std::rethrow_exception(captureException); } - visualizationThread.join(); std::cout << "Visualizer closed" << std::endl; } catch(const std::exception &e) diff --git a/source/Applications/Advanced/Visualization/CaptureVis3DInLoopWithKeypressExit/CaptureVis3DInLoopWithKeypressExit.cpp b/source/Applications/Advanced/Visualization/CaptureVis3DInLoopWithKeypressExit/CaptureVis3DInLoopWithKeypressExit.cpp index b3c95f71..ccceae7b 100644 --- a/source/Applications/Advanced/Visualization/CaptureVis3DInLoopWithKeypressExit/CaptureVis3DInLoopWithKeypressExit.cpp +++ b/source/Applications/Advanced/Visualization/CaptureVis3DInLoopWithKeypressExit/CaptureVis3DInLoopWithKeypressExit.cpp @@ -5,7 +5,8 @@ Capture point clouds, with color, from the Zivid camera, and visualize them in a #include #include -#include +#include +#include #include #include #ifdef _WIN32 @@ -71,70 +72,54 @@ int main() Zivid::Settings2D::Acquisitions{ Zivid::Settings2D::Acquisition{} } } } }; std::cout << "Capturing frame" << std::endl; - auto frame = camera.capture2D3D(settings); + const auto frame = camera.capture2D3D(settings); std::cout << "Setting up visualization" << std::endl; - std::atomic_bool visualizerRunning{ false }; - std::atomic_bool acceptEnd{ true }; - std::atomic_bool quitRequested{ false }; - auto visualizerPromise = std::promise(); - auto visualizerFuture = visualizerPromise.get_future(); + auto visualizer = Zivid::Visualization::Visualizer(); - std::thread visualizationThread([&frame, &visualizerPromise, &visualizerRunning, &acceptEnd, &quitRequested]() { - auto visualizer = Zivid::Visualization::Visualizer(); + std::cout << "Visualizing point cloud" << std::endl; + visualizer.showMaximized(); + visualizer.show(frame); + visualizer.resetToFit(); - // Pass the visualizer to the main thread - visualizerPromise.set_value(&visualizer); + std::atomic_bool visualizerRunning{ true }; + std::exception_ptr captureException; - std::cout << "Visualizing point cloud" << std::endl; - visualizer.showMaximized(); - visualizer.show(frame); - visualizer.resetToFit(); - - std::cout << "Running visualizer. Blocking until window closes." << std::endl; - do + std::thread captureThread([&camera, &settings, &visualizer, &visualizerRunning, &captureException]() { + try { - visualizerRunning = true; - visualizer.run(); - visualizerRunning = false; - - if(quitRequested) + std::cout << "Press 'q' in the terminal to quit " << std::endl; + while(visualizerRunning) { - break; + if(getKeyNonBlocking() == 'q') + { + std::cout << "Closing application because user pressed 'q'" << std::endl; + visualizer.close(); + break; + } + const auto newFrame = camera.capture2D3D(settings); + if(visualizerRunning) + { + visualizer.show(newFrame); + } + std::this_thread::sleep_for(std::chrono::milliseconds(10)); } - std::cout << "Visualizer window closed by user. It will be reopened if we're currently capturing." - << std::endl; - - } while(!acceptEnd); - }); - - // Get the visualizer handle in the main thread - auto visualizerHandle = visualizerFuture.get(); - - while(!visualizerRunning) - { - std::this_thread::sleep_for(std::chrono::milliseconds(1)); - } - std::cout << "Press 'q' in the terminal to quit " << std::endl; - while(visualizerRunning) - { - int key = getKeyNonBlocking(); - if(key == 'q') - { - std::cout << "Closing application because user pressed 'q'" << std::endl; - quitRequested = true; - visualizerHandle->close(); } - else + catch(...) { - acceptEnd = false; - frame = camera.capture2D3D(settings); - visualizerHandle->show(frame); - acceptEnd = true; + captureException = std::current_exception(); + visualizer.close(); } - std::this_thread::sleep_for(std::chrono::milliseconds(10)); + }); + + std::cout << "Running visualizer. Blocking until the window closes or 'q' is pressed." << std::endl; + visualizer.run(); + visualizerRunning = false; + captureThread.join(); + if(captureException) + { + std::rethrow_exception(captureException); } - visualizationThread.join(); std::cout << "Visualizer closed" << std::endl; } catch(const std::exception &e) diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt index ed5b7d9f..f44f9d0c 100644 --- a/source/CMakeLists.txt +++ b/source/CMakeLists.txt @@ -157,6 +157,7 @@ set(Clipp_DEPENDING CaptureViaGenICam CaptureWithSettingsFromYML CaptureWritePCLVis3D + Connect ConvertZDF GammaCorrection HandEyeCalibration diff --git a/source/Camera/Basic/Connect/Connect.cpp b/source/Camera/Basic/Connect/Connect.cpp index 4f55aa6f..0adedb00 100644 --- a/source/Camera/Basic/Connect/Connect.cpp +++ b/source/Camera/Basic/Connect/Connect.cpp @@ -1,15 +1,43 @@ /* Connect to a Zivid camera using the different available methods. -Replace the IP address and serial number in the code with the ones of your camera. +Replace the IP address, serial number and hostname in the code with the ones of your camera, +or provide them with --serial, --ip and --hostname. */ #include +#include + #include namespace { + struct CameraIdentifiers + { + std::string serialNumber{ "2020C0DE" }; + std::string ipAddress{ "172.28.60.5" }; + std::string hostname{ "zivid-2020C0DE.local" }; + }; + + CameraIdentifiers parseOptions(int argc, char **argv) + { + CameraIdentifiers identifiers; + auto cli = + (clipp::option("--serial") + & clipp::value("serial number", identifiers.serialNumber).doc("Serial number of the camera"), + clipp::option("--ip") & clipp::value("ip address", identifiers.ipAddress).doc("IP address of the camera"), + clipp::option("--hostname") + & clipp::value("hostname", identifiers.hostname).doc("Hostname of the camera")); + + if(!clipp::parse(argc, argv, cli)) + { + std::cout << clipp::usage_lines(cli, "Connect") << std::endl; + throw std::runtime_error{ "Invalid usage" }; + } + return identifiers; + } + void printDiscoveredCameras(Zivid::Application &zivid) { std::cout << "Discovered cameras:" << std::endl; @@ -21,18 +49,16 @@ namespace } } // namespace -int main() +int main(int argc, char **argv) { try { + const auto identifiers = parseOptions(argc, argv); + Zivid::Application zivid; printDiscoveredCameras(zivid); - std::cout << "The serial number, IP address and hostname below are placeholders. " - "Replace them with the ones of your camera." - << std::endl; - { std::cout << "Connecting to the first available camera" << std::endl; auto camera = zivid.connectCamera(); @@ -40,22 +66,22 @@ int main() } { - std::cout << "Connecting to the camera with a specific serial number" << std::endl; - auto camera = zivid.connectCamera(Zivid::CameraInfo::SerialNumber{ "2020C0DE" }); + std::cout << "Connecting to the camera with serial number " << identifiers.serialNumber << std::endl; + auto camera = zivid.connectCamera(Zivid::CameraInfo::SerialNumber{ identifiers.serialNumber }); camera.disconnect(); } { - std::cout << "Connecting to the camera at a specific IP address" << std::endl; - auto camera = zivid.connectCamera(Zivid::CameraAddress{ "172.28.60.5" }); + std::cout << "Connecting to the camera at IP address " << identifiers.ipAddress << std::endl; + auto camera = zivid.connectCamera(Zivid::CameraAddress{ identifiers.ipAddress }); camera.disconnect(); } { - std::cout << "Connecting to the camera at a specific hostname" << std::endl; + std::cout << "Connecting to the camera at hostname " << identifiers.hostname << std::endl; // The default hostname format is "zivid-.local". // The hostname cannot be read or set through the SDK. - auto camera = zivid.connectCamera(Zivid::CameraAddress{ "zivid-2020C0DE.local" }); + auto camera = zivid.connectCamera(Zivid::CameraAddress{ identifiers.hostname }); camera.disconnect(); }