# AprilTag

AprilTag node takes [ImgFrame](https://docs.luxonis.com/software-v3/depthai/depthai-components/messages/img_frame.md) as input and
outputs detected AprilTag markers
([AprilTags](https://docs.luxonis.com/software-v3/depthai/depthai-components/messages/april_tags.md) message). It's based on the
[AprilRobotics/apriltag](https://github.com/AprilRobotics/apriltag) repository, and runs optimized detection algorithms on the CPU
(on [RVC4](https://docs.luxonis.com/hardware/platform/rvc/rvc4.md) octacore itself, or on the host when using
[RVC2](https://docs.luxonis.com/hardware/platform/rvc/rvc2.md)-based devices).

AprilTag marker is a visual [fiducial marker](https://en.wikipedia.org/wiki/Fiducial_marker), so it's similar to ArUco, ARTag and
ARToolKit markers.

## How to place it

#### Python

```python
pipeline = dai.Pipeline()
hostCamera = pipeline.create(dai.node.Camera).build()
aprilTagNode = pipeline.create(dai.node.AprilTag)
# Link 1920x1080 output to AprilTag input
hostCamera.requestOutput((1920, 1080)).link(aprilTagNode.inputImage)
# Create output queue for passthrough frames
passthroughOutputQueue = aprilTagNode.passthroughInputImage.createOutputQueue()
# Create output queue for detected AprilTags
outQueue = aprilTagNode.out.createOutputQueue()
```

#### C++

```cpp
dai::Pipeline pipeline;
auto cameraNode = pipeline.create<dai::node::Camera>()->build();
auto aprilTagNode = pipeline.create<dai::node::AprilTag>();
// Link 1920x1080 output to AprilTag input
auto outputCam = cameraNode->requestOutput(std::make_pair(1920, 1080));
outputCam->link(aprilTagNode->inputImage);
// Create output queue for passthrough frames
auto passthroughOutputQueue = aprilTagNode->passthroughInputImage.createOutputQueue();
// Create output queue for detected AprilTags
auto outQueue = aprilTagNode->out.createOutputQueue();
```

## Inputs and Outputs

## Limitations

#### RVC2

On the [RVC2](https://docs.luxonis.com/hardware/platform/rvc/rvc2.md) devices, the AprilTag node runs on the host computer, so the
performance will be limited by the host CPU.

#### RVC4

[RVC4](https://docs.luxonis.com/hardware/platform/rvc/rvc4.md) can process 1080P frames at about 190FPS, while consuming 25% of
the CPU. We used [this script](https://gist.github.com/Erol444/ede0301758156ef0e457f744954d3137) to benchmark the performance, and
here were the results:

```bash
[441340706] [10.12.101.114] [1725552371.591] [BenchmarkIn(3)] [warning] FPS: 191.80461
[441340706] [10.12.101.114] [1725552371.592] [BenchmarkIn(3)] [warning] Messages took 52.13639 s
[441340706] [10.12.101.114] [1725552371.593] [BenchmarkIn(3)] [warning] Average latency is 0 s
```

## Examples of functionality

 * [AprilTags from camera](https://docs.luxonis.com/software-v3/depthai/examples/april_tags/april_tags.md)
 * [AprilTags from camera 12MP](https://docs.luxonis.com/software-v3/depthai/examples/april_tags/april_tags_12mp.md)
 * [AprilTags on image replay](https://docs.luxonis.com/software-v3/depthai/examples/april_tags/april_tags_replay.md)

## Reference

### dai::node::AprilTag

Kind: class

AprilTag node.

#### std::shared_ptr< AprilTagConfig > initialConfig

Kind: variable

Initial config to use when calculating spatial location data.

#### Input inputConfig

Kind: variable

Input AprilTagConfig message with ability to modify parameters in runtime. Default queue is non-blocking with size 4.

#### Input inputImage

Kind: variable

Input message with depth data used to retrieve spatial information about detected object. Default queue is non-blocking with size
4.

#### Output out

Kind: variable

Outputs AprilTags message that carries spatial location results.

#### Output outConfig

Kind: variable

Outputs AprilTagConfig message that contains current configuration.

#### Output passthroughInputImage

Kind: variable

Passthrough message on which the calculation was performed. Suitable for when input queue is set to non-blocking behavior.

#### AprilTag()

Kind: function

#### AprilTag(std::unique_ptr< Properties > props)

Kind: function

#### void setWaitForConfigInput(bool wait)

Kind: function

Specify whether or not wait until configuration message arrives to inputConfig Input. parameters: wait: True to wait for
configuration message, false otherwise.

#### bool getWaitForConfigInput()

Kind: function

Get whether or not wait until configuration message arrives to inputConfig Input.

#### void setNumThreads(int numThreads)

Kind: function

Set number of threads to use for AprilTag detection. parameters: numThreads: Number of threads to use.

#### int getNumThreads()

Kind: function

Get number of threads to use for AprilTag detection. return: Number of threads to use.

#### void setRunOnHost(bool runOnHost)

Kind: function

Specify whether to run on host or device By default, the node will run on device.

#### bool runOnHost()

Kind: function

Check if the node is set to run on host

#### void run()

Kind: function

#### void buildInternal()

Kind: function

Function called from within the

#### DeviceNodeCRTP()

Kind: function

#### DeviceNodeCRTP(const std::shared_ptr< Device > & device)

Kind: function

#### DeviceNodeCRTP(std::unique_ptr< Properties > props)

Kind: function

#### DeviceNodeCRTP(std::unique_ptr< Properties > props, bool confMode)

Kind: function

#### DeviceNodeCRTP(const std::shared_ptr< Device > & device, std::unique_ptr< Properties > props, bool confMode)

Kind: function

### Need assistance?

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