Isaac ROSでWebカメラからAprilTagを検出する

# はじめに
こちらでIsaac ROSの環境構築を行いました。
今回はAprilTagの検出をやってみます。

https://qiita.com/kawai-yuuki/items/e23214562e2da88d7295



使用したPC環境です。
| 項目 | バージョン |
|:-:|:-:|
| CPU | AMD Ryzen 5 3600 |
| GPU | Geforce RTX 3060 |
| OS | Ubuntu22.04 |
| Webカメラ| オーム電機 WB-CA200N |
| Isaac ROS | 3.2 |

# AprilTagについて
AprilTagはミシガン大学によって開発されたARマーカーの一種です。カメラ画像から検出されると撮影したカメラからマーカーまでの相対的な三次元位置情報を推定できます。

https://april.eecs.umich.edu/software/apriltag

公式のROSパッケージも存在しますが、今回はIsaac ROSのパッケージ使用し、GPUで処理を実行します。

今回使用するAprilTagの種類です。
| 項目 | バージョン |
|:-:|:-:|
| タグファミリー | 36h11 |
| サイズ | 0.12 [m] |
| ID | 0 |

![tag36_11_00000_15cm.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3470204/2f34452b-fef7-4ae4-9a18-d500c3d0e633.png)



# 準備
Isaac ROSのAprilTagのドキュメントです。

https://nvidia-isaac-ros.github.io/repositories_and_packages/isaac_ros_apriltag/index.html

流れとしては、

1. クイックスタートをrosbagで実行できることを確認する
2. USBカメラを使用したチュートリアルへ進む
2. USBカメラのキャリブレーション作業を済ませる
2. 準備完了

となります。
基本的にはドキュメントの指示通りに進めていきます。

# 注意すべき点
ドキュメントの作業を進める上で私が実施した独自の作業をまとめます。

* カメラキャリブレーションにはチェッカーボードが必要。A4用紙に印刷できる大きさのものを用意した。
* USBカメラの解像度は自由に設定できるが、キャリブレーション時の解像度からタグの検出を行うところまで一貫した値を用いること。（今回は640X480を選択）解像度がキャリブレーション時と異なると、正しい位置推定ができなかった。
* タグのデフォルトのサイズは0.22 [m]であり、A4用紙一枚に印刷できない。よって0.12 [m]にリサイズし使用した。
* タグのリサイズにより、用意されていたローンチファイルの内容を一部変更する必要があった。変更後のローンチファイルを以下に示す。（自由に使ってください）

```isaac_ros_apriltag_usb_cam.launch.py
import os

from ament_index_python.packages import get_package_share_directory
import launch
from launch.actions import DeclareLaunchArgument
from launch.substitutions import LaunchConfiguration
from launch_ros.actions import ComposableNodeContainer
from launch_ros.descriptions import ComposableNode


def generate_launch_description():
    launch_args = [
        DeclareLaunchArgument(
            'camera_width',
            default_value='640',
            description='The USB camera input width.'),
        DeclareLaunchArgument(
            'camera_height',
            default_value='480',
            description='The USB camera input height.'),
        DeclareLaunchArgument(
            'size',
            default_value='0.12',
            description='The size of the AprilTag in meters.'),
    ]

    camera_width = LaunchConfiguration('camera_width')
    camera_height = LaunchConfiguration('camera_height')
    size = LaunchConfiguration('size')

    rectify_node = ComposableNode(
        package='isaac_ros_image_proc',
        plugin='nvidia::isaac_ros::image_proc::RectifyNode',
        name='rectify',
        namespace='',
        parameters=[{
            'output_width': camera_width,
            'output_height': camera_height,
        }]
    )

    apriltag_node = ComposableNode(
        package='isaac_ros_apriltag',
        plugin='nvidia::isaac_ros::apriltag::AprilTagNode',
        name='apriltag',
        namespace='',
        remappings=[
            ('image', 'image_rect'),
            ('camera_info', 'camera_info_rect')
        ],
        parameters=[{
            'size': size,
        }]
    )

    usb_cam_params_path = os.path.join(
        get_package_share_directory('isaac_ros_apriltag'),
        'config',
        'usb_cam_params.yaml'
    )
    usb_cam_node = ComposableNode(
        package='usb_cam',
        plugin='usb_cam::UsbCamNode',
        name='usb_cam',
        parameters=[usb_cam_params_path]
    )

    apriltag_container = ComposableNodeContainer(
        package='rclcpp_components',
        name='apriltag_container',
        namespace='',
        executable='component_container_mt',
        composable_node_descriptions=[
            rectify_node,
            apriltag_node,
            usb_cam_node
        ],
        output='screen'
    )

    return launch.LaunchDescription(launch_args + [apriltag_container])
```

### 実行結果

これでうまくいったはずです。TFの距離推定も概ね間違いないです。

![apriltag_detection.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3470204/41ef8919-258f-417a-ae64-3d4fc8eea854.gif)

今回はデフォルト設定の30 [FPS]で実行しましたが、更に高いフレームレートでも余裕で実行できるかと思います。