# IR Projectors Control

Displays left/right mono streams and lets you change [IR dot
projector](https://docs.luxonis.com/hardware/platform/features/ir-perception/dot-projector.md) and flood light (aka. flood LED)
intensities on the device at runtime. Enabling flood lights allows for better depth detection. Controls: `W/S` for dot intensity,
`A/D` for flood intensity, `Q` to quit. Works only with [Pro-series devices](#Supported%20devices).

## Demo

This example requires the DepthAI v3 API, see [installation instructions](https://docs.luxonis.com/software-v3/depthai.md).

## Supported devices

 * OAK4-D Pro
 * OAK-D Pro W PoE
 * OAK-D Pro W
 * OAK-D Pro PoE
 * OAK-D Pro

## Pipeline

## Source code

#### Python

```python
#!/usr/bin/env python3

import cv2
import depthai as dai

dot_intensity = 1
DOT_STEP = 0.1

flood_intensity = 1
FLOOD_STEP = 0.1

# Create pipeline
device = dai.Device()
with dai.Pipeline(device) as pipeline:
    monoLeft = pipeline.create(dai.node.Camera).build(dai.CameraBoardSocket.CAM_B)
    monoRight = pipeline.create(dai.node.Camera).build(dai.CameraBoardSocket.CAM_C)

    # Linking
    monoLeftOut = monoLeft.requestFullResolutionOutput(type=dai.ImgFrame.Type.NV12)
    monoRightOut = monoRight.requestFullResolutionOutput(type=dai.ImgFrame.Type.NV12)

    leftQueue = monoLeftOut.createOutputQueue()
    rightQueue = monoRightOut.createOutputQueue()

    pipeline.start()
    pipeline.getDefaultDevice().setIrLaserDotProjectorIntensity(dot_intensity)
    pipeline.getDefaultDevice().setIrFloodLightIntensity(flood_intensity)
    while pipeline.isRunning():
        leftSynced = leftQueue.get()
        rightSynced = rightQueue.get()
        assert isinstance(leftSynced, dai.ImgFrame)
        assert isinstance(rightSynced, dai.ImgFrame)
        cv2.imshow(f"left", leftSynced.getCvFrame())
        cv2.imshow(f"right", rightSynced.getCvFrame())

        key = cv2.waitKey(1)
        if key == ord('q'):
            pipeline.stop()
            break
        elif key == ord("w"):
            dot_intensity += DOT_STEP
            if dot_intensity > 1:
                dot_intensity = 1
            pipeline.getDefaultDevice().setIrLaserDotProjectorIntensity(dot_intensity)
            print(f"Dot intensity: {dot_intensity}")
        elif key == ord("s"):
            dot_intensity -= DOT_STEP
            if dot_intensity < 0:
                dot_intensity = 0
            pipeline.getDefaultDevice().setIrLaserDotProjectorIntensity(dot_intensity)
            print(f"Dot intensity: {dot_intensity}")
        elif key == ord("a"):
            flood_intensity += FLOOD_STEP
            if flood_intensity > 1:
                flood_intensity = 1
            pipeline.getDefaultDevice().setIrFloodLightIntensity(flood_intensity)
            print(f"Flood intensity: {flood_intensity}")
        elif key == ord("d"):
            flood_intensity -= FLOOD_STEP
            if flood_intensity < 0:
                flood_intensity = 0
            pipeline.getDefaultDevice().setIrFloodLightIntensity(flood_intensity)
            print(f"Flood intensity: {flood_intensity}")
```

#### C++

```cpp
#include <atomic>
#include <csignal>
#include <iostream>
#include <memory>
#include <opencv2/opencv.hpp>

#include "depthai/depthai.hpp"

// Global flag for graceful shutdown
std::atomic<bool> quitEvent(false);

// Signal handler
void signalHandler(int signum) {
    quitEvent = true;
}

// Constants for intensity control
constexpr float DOT_STEP = 0.1f;
constexpr float FLOOD_STEP = 0.1f;

int main() {
    // Set up signal handlers
    signal(SIGTERM, signalHandler);
    signal(SIGINT, signalHandler);

    try {
        // Create device
        auto device = std::make_shared<dai::Device>();

        // Create pipeline
        dai::Pipeline pipeline(device);

        // Create camera nodes
        auto monoLeft = pipeline.create<dai::node::Camera>()->build(dai::CameraBoardSocket::CAM_B);
        auto monoRight = pipeline.create<dai::node::Camera>()->build(dai::CameraBoardSocket::CAM_C);

        // Configure outputs
        auto monoLeftOut = monoLeft->requestFullResolutionOutput(dai::ImgFrame::Type::NV12);
        auto monoRightOut = monoRight->requestFullResolutionOutput(dai::ImgFrame::Type::NV12);

        // Create output queues
        auto leftQueue = monoLeftOut->createOutputQueue();
        auto rightQueue = monoRightOut->createOutputQueue();

        // Start pipeline
        pipeline.start();

        // Initialize intensities
        float dot_intensity = 1.0f;
        float flood_intensity = 1.0f;

        // Set initial intensities
        device->setIrLaserDotProjectorIntensity(dot_intensity);
        device->setIrFloodLightIntensity(flood_intensity);

        std::cout << "Controls:" << std::endl;
        std::cout << "  W/S: Increase/decrease dot projector intensity" << std::endl;
        std::cout << "  A/D: Increase/decrease flood light intensity" << std::endl;
        std::cout << "  Q: Quit" << std::endl;

        while(pipeline.isRunning() && !quitEvent) {
            auto leftSynced = leftQueue->get<dai::ImgFrame>();
            auto rightSynced = rightQueue->get<dai::ImgFrame>();

            if(leftSynced == nullptr || rightSynced == nullptr) continue;

            cv::imshow("left", leftSynced->getCvFrame());
            cv::imshow("right", rightSynced->getCvFrame());

            int key = cv::waitKey(1);
            if(key == 'q') {
                break;
            } else if(key == 'w') {
                dot_intensity += DOT_STEP;
                if(dot_intensity > 1.0f) dot_intensity = 1.0f;
                device->setIrLaserDotProjectorIntensity(dot_intensity);
                std::cout << "Dot intensity: " << dot_intensity << std::endl;
            } else if(key == 's') {
                dot_intensity -= DOT_STEP;
                if(dot_intensity < 0.0f) dot_intensity = 0.0f;
                device->setIrLaserDotProjectorIntensity(dot_intensity);
                std::cout << "Dot intensity: " << dot_intensity << std::endl;
            } else if(key == 'a') {
                flood_intensity += FLOOD_STEP;
                if(flood_intensity > 1.0f) flood_intensity = 1.0f;
                device->setIrFloodLightIntensity(flood_intensity);
                std::cout << "Flood intensity: " << flood_intensity << std::endl;
            } else if(key == 'd') {
                flood_intensity -= FLOOD_STEP;
                if(flood_intensity < 0.0f) flood_intensity = 0.0f;
                device->setIrFloodLightIntensity(flood_intensity);
                std::cout << "Flood intensity: " << flood_intensity << std::endl;
            }
        }

        // Cleanup
        pipeline.stop();
        pipeline.wait();

    } catch(const std::exception& e) {
        std::cerr << "Error: " << e.what() << std::endl;
        return 1;
    }

    return 0;
}
```

### Need assistance?

Head over to [Discussion Forum](https://discuss.luxonis.com/) for technical support or any other questions you might have.
