[ROS1/ROS2] Windows11でROSの環境構築

本記事はROS 2 アドベントカレンダーの16日目の記事です。

https://qiita.com/advent-calendar/2023/ros2

# はじめに
Qiita初投稿になります、nakajiと申します。
ROSは研究で使い始めて2年半くらいで、主にロボットアームを扱っています。

ROSを使っている皆さんは、Ubuntuで開発している人がほとんどだと思います。
ただ、ハードウェアやってるとWindowsのみ対応のソフトも多いので、
開発マシンはUbuntuだけどノートPCはWindowsという人も多いのではないでしょうか？
ノートPCでROSが使えると開発が捗りますね！
そこで、本記事ではWindowsでのROS環境構築について共有します。

本記事は環境構築の説明が長いので、説明不要な人向けに結論だけ書いておくと、
「Windows11のWSL2ではGUIが標準で使える(WSLg)ので、ROSの環境構築をするときに、Xサーバや仮想デスクトップ+VNCはもう不要」
です。
シミュレータだけでなく、ロボットアーム実機と接続して動かせることも確認しています。

追記
この記事を書いていて気付いたのですが、Windows11だけでなく、Windows10でもWSLgが使えるようになったそうです

https://qiita.com/y-tsutsu/items/6bc65c0ce4d20a82a417

# ROS環境構築の種類
ROSの環境構築は大きく分けて2つの方法があるかと思います。
なお、この記事では②を扱います。
## ①直接インストールしてROS環境を構築する
以前は主流だったかと思いますが、個人的にはお勧めしない方法です。
ROSの環境は依存関係が複雑であり、同じコマンドで環境を作ってもPCの環境によって動作しないこともよくあります。
また、特にROS2は頻繁にアップデートされるのでいつの間にか動かなくなり、最初から環境構築やり直したいこともよくあります。
サクッと環境を作ってミスったら作り直す、そんな時は②の方法が便利です。

## ②仮想環境にROS環境を構築する
最近はこっちが主流になってきたかと思います。
仮想環境上にROS(と必要な周辺ソフトウェア)をインストールしていきます。
仮想環境にも色々あるのですが、WindowsだとWSL2+Dockerが便利かと思います。
Tiryohさんの記事が知られているのではないでしょうか。

https://qiita.com/Tiryoh/items/ed7eecfac2ca9c7bf09d

Win10までは、僕もこちらの環境をベースに使っていました。
ただ、ちょっと気になっていた点として、仮想デスクトップ+VNCは動作が重たいです。
最近Win11に乗り換えた際に、仮想デスクトップがなくてもよいことに気が付きました。

そもそもなぜ仮想デスクトップを使っていたのかというと、WSL2では標準でGUIが表示できないからでした。
そのため、Windows上にXサーバを別途立ち上げて、WSLからXサーバに接続してGUI表示を行う、
もしくは先ほどの紹介のように仮想デスクトップを立ちあげてVNCでアクセスする、
といった方法が必要でした。

しかし、なんと、Windows11からはWSL2標準でGUIが使えるようになりました。
[WSLg](https://github.com/microsoft/wslg)というシステムだそうです。
これで面倒な仕組みを使う必要がなくなっただけでなく、ネイティブのUbuntuとWSL2で同じ方法で環境構築ができるようになりました。

# WindowsでのROS環境構築の例
参考までに、僕のROS環境構築例とメモ書きになります。
- 注意
    - docker composeでdevやdisplayの環境を設定しておくと便利です。
    - network_modeがhostなので、セキュリティを考慮しておらずあくまで開発用です。運用で使う際は注意してください。
- コマンド
    - ```docker compose -p ${USER} -f compose.yaml build```でDockerイメージを作成できます。
    - ```docker compose -p ${USER} -f compose.yaml up -d```でDockerコンテナを作成できます。
    - ``xhost +local:```でXサーバーへの接続許可を出してから、```docker exec -it  ${CONTAINER_NAME} bash -i``でDocker環境になかに入ってください。
        - ${CONTAINER_NAME}は下記のcompose.yamlの例だとROS1 noeticの場合`${USER}-ros-noetic-1`、ROS2 humbleの場合`${USER}-ros2-humble-1`となります。


- WSL2
    - WSL2はROSのバージョンに応じて複数使い分けています。
        - ROS1 noetic: WSL2 20.04
        - ROS2 humble: WSL2 22.04
- Docker Desktop
    - Dockerを使っています。
    - 設定でWSL2を有効にしておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1885179/41e67f2e-3cd1-27bc-e4ad-fd1b3c31b0eb.png)

- VSCode
    - WSLの拡張機能を使って、WSL環境に接続できるので便利です。
    - Dockerの環境に接続するにはRemote-Containersという拡張機能が便利です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1885179/71c133d3-6439-1c36-d068-d10bb8680e27.png)

<details><summary>ROS1 noeticのDockerfile</summary>



```dockerfile

FROM osrf/ros:noetic-desktop-full
LABEL maintainer="Nakajima<yusaku_nakajima@ap.eng.osaka-u.ac.jp>"

# Ignore keybourd layout seting
ENV DEBIAN_FRONTEND=noninteractive

# set timezone
RUN ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime
RUN apt-get update \
    && apt-get install -y git tzdata

RUN date
# Install apt packages
RUN apt-get update && apt-get install -y \
    git \
    vim \
    nano \
    wget \
    tmux \
    curl \
    terminator \
    iputils-ping net-tools \
    libglib2.0-0 \
    libgl1-mesa-dev \
    && apt-get clean \
    && rm -rf /var/lib/apt/lists/*

# Install ROS packages
RUN apt-get update && apt-get install -y \
    python3-pip \
    python3-catkin-tools \
    ros-noetic-joy ros-noetic-teleop-twist-joy \
    ros-noetic-teleop-twist-keyboard ros-noetic-laser-proc \
    ros-noetic-rgbd-launch ros-noetic-rosserial-arduino \
    ros-noetic-rosserial-python ros-noetic-rosserial-client \
    ros-noetic-rosserial-msgs ros-noetic-amcl ros-noetic-map-server \
    ros-noetic-move-base ros-noetic-urdf ros-noetic-xacro \
    ros-noetic-compressed-image-transport ros-noetic-rqt* ros-noetic-rviz \
    ros-noetic-interactive-markers \
    ros-noetic-dynamixel-sdk \
    ros-noetic-realsense2-camera \
    ros-noetic-realsense2-description \
    && apt-get clean \
    && rm -rf /var/lib/apt/lists/*

# Install vcstools
RUN apt-get update && apt-get install -y \
    python3-vcstool \
    && apt-get clean \
    && rm -rf /var/lib/apt/lists/*


# Create ROS workspace
RUN echo "source /opt/ros/noetic/setup.bash" >> /root/.bashrc
RUN echo "source /home/ubuntu/onolab/catkin_ws/devel/setup.bash" >> /root/.bashrc
RUN echo "export ROS_MASTER_URI=http://localhost:11311" >> /root/.bashrc
RUN echo "export ROS_HOSTNAME=localhost" >> /root/.bashrc



```
</details>

<details><summary>ROS1 noeticのcompose.yaml</summary>


```yaml
version: "3.8"

################################################################################

services:
  ros-noetic:
    hostname: test_ros_noetic
    runtime: ${DOCKER_RUNTIME}
    privileged: true
    image: ros_noetic
    environment:
      # Pass host user information.
      - HOST_USER=${USER}
      - HOST_UID=1000
      - HOST_GID=1000
      # Display X Server GUI.
      - DISPLAY
      - QT_X11_NO_MITSHM=1
    build:
      context: .
      dockerfile: ./Dockerfile
    volumes:
      # Map ROS workspace folders.
      - ../:/home/ubuntu/ros/
      # Grant display access to X Server.
      - /tmp/.X11-unix:/tmp/.X11-unix
      # Grant access to usb ports
      - /dev/:/dev/
    network_mode: "host"
    extra_hosts:
      - "host:127.0.0.1" # Seems that this might be needed for ROS networking
      - "host:192.168.0.2" # The host PC
      - "ur:192.168.0.3" # UR IP
    expose:
      - "50001" # send commnad to UR
      - "50002" # external control of UR
      - "50003" # recerve commnad from UR
      - "50004" # script_command_port of UR

    tty: true

```
</details>

<details><summary>ROS2 humbleのDockerfile</summary>


```dockerfile

FROM osrf/ros:humble-desktop
LABEL maintainer="YusakuNakajima<yusaku_nakajima@ap.eng.osaka-u.ac.jp>"

# Ignore keybourd layout seting
ENV DEBIAN_FRONTEND=noninteractive

# set timezone
RUN ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime
RUN apt-get update \
    && apt-get install -y git tzdata
RUN date

# Install apt packages
RUN apt-get update && apt-get install -y \
    git \
    vim \
    nano \
    wget \
    tmux \
    curl \
    terminator \
    iputils-ping \
    net-tools \
    python3-pip \
    && apt-get clean \
    && rm -rf /var/lib/apt/lists/*


# Install ROS packages
RUN apt-get update -q && \
    apt-get install -y \
    ros-humble-rmw-cyclonedds-cpp \
    && apt-get clean \ 
    && rm -rf /var/lib/apt/lists/*

# Setup ROS enviroments
RUN echo "source /opt/ros/humble/setup.bash" >> /root/.bashrc
RUN echo "source /home/ubuntu/onolab/onolab_ws/install/setup.bash" >> /root/.bashrc
# Argcomplete for colcon
RUN echo "source /usr/share/colcon_argcomplete/hook/colcon-argcomplete.bash" >> /root/.bashrc


```
</details>

<details><summary>ROS2 humbleのcompose.yaml</summary>



```yaml
version: "3.8"

################################################################################

services:
  ros2-humble:
    hostname: test_ros2_humble
    runtime: ${DOCKER_RUNTIME}
    privileged: true
    network_mode: host # Use host network(IP and ports).
    extra_hosts:
      - "host:192.168.0.2" # The host PC
      - "ur:192.168.0.3" # UR IP
    expose:
      - "50001" # send commnad to UR
      - "50002" # external control of UR
      - "50003" # recerve commnad from UR
      - "50004" # script_command_port of UR
    environment:
      # Pass host user information.
      - HOST_USER=${USER}
      - HOST_UID=1000
      - HOST_GID=1000
      # Display X Server GUI.
      - DISPLAY
      - QT_X11_NO_MITSHM=1
      # Set ROS environment variables. It is instead of writing them in .bashrc.
      - ROS_DOMAIN_ID=1
      - ROS_VERSION=2
      - ROS_PYTHON_VERSION=3
      - ROS_DISTRO=humble
      - ROS_LOCALHOST_ONLY=1
      - RMW_IMPLEMENTATION=rmw_fastrtps_cpp

    image: onolab_ros2_humble
    build:
      dockerfile: ./Dockerfile
    volumes:
      # Map ROS workspace folders.
      - ../:/home/ubuntu/ros2/
      # Grant display access to X Server.
      - /tmp/.X11-unix:/tmp/.X11-unix
      # Grant access to usb ports
      - /dev/:/dev/
    tty: true
```
</details>