Skip to content
Kim JeongHan edited this page Aug 17, 2023 · 2 revisions

Project ์†Œ๊ฐœ

ROS_dev_template

์šฐ๋ฆฌ๋Š” ROS_dev_template๋ผ๋Š” ํŒจํ‚ค์ง€๋ฅผ ์‚ฌ์šฉํ•ด์„œ ํ”„๋กœ์ ํŠธ๋ฅผ ์ง„ํ–‰ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

ํ•ด๋‹น ํŒจํ‚ค์ง€๋ฅผ ์ข€ ๋” ์ž˜ ์‚ฌ์šฉํ•˜๊ณ  ๋ถˆํ•„์š”ํ•œ ์ž‘์—…์„ ์ค„์ด๊ธฐ ์œ„ํ•ด์„œ ์šฐ๋ฆฌ๋Š” ๋‹ค์–‘ํ•œ ์†Œํ”„ํŠธ์›จ์–ด ํ”„๋กœ๊ทธ๋žจ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ, ๊ทธ๋Ÿฌํ•œ ํ˜„์—…์—์„œ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋Š” ์†Œํ”„ํŠธ์›จ์–ด ํ”„๋กœ๊ทธ๋žจ์„ ์†Œ๊ฐœํ•˜๊ณ , ๊ทธ๋Ÿฌํ•œ ํ”„๋กœ๊ทธ๋žจ์„ ์‚ฌ์šฉํ•ด์„œ ์–ด๋– ํ•œ ์‹์œผ๋กœ ํ”„๋กœ์ ํŠธ๋ฅผ ๊ด€๋ฆฌํ•˜๊ณ  ๊ตฌ์„ฑํ•˜๋ฉด ์ข‹์„์ง€์— ๋Œ€ํ•œ ๋‚ด์šฉ์„ ๊ณต์œ ํ•˜๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

๋Œ€๋ถ€๋ถ„์˜ ์†Œํ”„ํŠธ์›จ์–ด ํ”„๋กœ๊ทธ๋žจ๋“ค์€ ๊ธฐ๋ณธ์ ์œผ๋กœ Web & App ๊ฐœ๋ฐœ์ž๋“ค์ด ์ฃผ๋กœ ๋งŒ๋“ค์—ˆ๊ธฐ์—, nodejs ๋“ฑ Web&app ๊ด€๋ จ ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ์‰ฝ๊ฒŒ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด ๊ตฌ์„ฑ๋˜์–ด์žˆ์Šต๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” ๊ทธ๋Ÿฌํ•œ ํ”„๋กœ๊ทธ๋žจ๋“ค์„ ROS2 ๊ฐœ๋ฐœ์„ ์‰ฝ๊ฒŒ ํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•  ์˜ˆ์ •์ด๊ณ , ๊ทธ์— ๋งž๊ฒŒ ์ปค์Šคํ„ฐ๋งˆ์ด์ง• ํ•˜์—ฌ ์‚ฌ์šฉํ•˜๋ ค ํ•ฉ๋‹ˆ๋‹ค.

Coding Style Guide๋Š” ๋”ฐ๋กœ ์ž‘์„ฑ๋œ ๊ธ€์„ ๋ณด๋ฉด ์ข€๋” ์ž์„ธํ•œ ์‚ฌ์šฉ์— ๋Œ€ํ•œ ๋‚ด์šฉ์„ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด ๊ธ€์—์„œ๋Š” ์ฃผ๋กœ docker, git hook, vscode extension, branch์ „๋žต์— ๋Œ€ํ•œ ๋‚ด์šฉ์„ ์ข€๋” ์ž์„ธํžˆ ๋‹ค๋ฃจ๊ฒ ์Šต๋‹ˆ๋‹ค.

Docker

์ง€๋Šฅํ˜•๋กœ๋ด‡์‚ฌ์—…๋‹จ Git & Docker ์Šคํ„ฐ๋””

๊ธฐ๋ณธ์ ์ธ Docker์˜ ๋Œ€ํ•œ ๋‚ด์šฉ์€ ํ•ด๋‹น ์Šคํ„ฐ๋”” ๋‚ด์šฉ์— ์ž์„ธํ•˜๊ฒŒ ๋‹ด์•„ ๋†“์•˜์œผ๋‹ˆ, ์šฐ๋ฆฌ๋Š” ์šฐ๋ฆฌ ํ”„๋กœ์ ํŠธ์— ์ ์šฉ๋˜์–ด์žˆ๋Š” dockerfile, docker-compose.yaml ์— ๋Œ€ํ•ด์„œ ๋‹ค๋ฃจ๊ณ ์ž ํ•ฉ๋‹ˆ๋‹ค.

# ROS distribution to use
ARG ROS_DISTRO=humble

########################################
# Base Image for gole Simulation #
########################################
FROM osrf/ros:${ROS_DISTRO}-desktop-full as base
ARG REPO
ENV ROS_DISTRO=${ROS_DISTRO}
SHELL ["/bin/bash", "-c"]

ARG DEBIAN_FRONTEND=noninteractive

# Install basic apt packages
RUN --mount=type=cache,target=/var/cache/apt,id=apt \
    apt-get update && apt-get upgrade -y \
    && apt-get install -q -y --no-install-recommends \
    build-essential \
    ccache \
    cmake \
    lld \
    python3-colcon-common-extensions \
    python3-colcon-coveragepy-result \
    python3-colcon-mixin \
    git libcanberra-gtk-module libcanberra-gtk3-module fuse3 libqt5svg5-dev \
    python3-pip python3-opencv python3-tk python3-pyqt5.qtwebengine \
    && rm -rf /var/lib/apt/lists/*

# Install additional Python modules
RUN pip3 install matplotlib transforms3d \
    pytest pytest-cov pytest-mock pytest-xdist

# Use Cyclone DDS as middleware and install ros2 packages
RUN apt-get update && apt-get install -y --no-install-recommends \
    ros-${ROS_DISTRO}-rmw-cyclonedds-cpp \
    ros-${ROS_DISTRO}-navigation2 \
    ros-${ROS_DISTRO}-nav2-bringup
ENV RMW_IMPLEMENTATION=rmw_cyclonedds_cpp

# Create Colcon workspace with external dependencies
RUN mkdir -p /upstream_ws/src
WORKDIR /upstream_ws/src
COPY dependencies.repos .
RUN vcs import < dependencies.repos

# Build the base Colcon workspace, installing dependencies first.
WORKDIR /upstream_ws
RUN source /opt/ros/${ROS_DISTRO}/setup.bash \
    && rosdep update && apt-get update -y \
    && rosdep install --from-paths src --ignore-src --rosdistro ${ROS_DISTRO} -y \
    && rm -rf /var/lib/apt/lists/* \
    && colcon build --mixin release lld

# Download Groot2 AppImage and place it in the home folder.
# WORKDIR /root/
# RUN curl -o Groot2.AppImage https://s3.us-west-1.amazonaws.com/download.behaviortree.dev/groot2_linux_installer/Groot2-v1.0.1-x86_64.AppImage \
#     && chmod a+x Groot2.AppImage

# Remove display warnings
RUN mkdir /tmp/runtime-root
ENV XDG_RUNTIME_DIR "/tmp/runtime-root"
RUN chmod -R 0700 /tmp/runtime-root
ENV NO_AT_BRIDGE 1

# Set up the entrypoint
WORKDIR /upstream_ws
COPY ./docker/entrypoint.sh /
ENTRYPOINT [ "/entrypoint.sh" ]

###########################################
# Overlay Image for gole Simulation #
###########################################
FROM base AS overlay

# Create an overlay Colcon workspace
RUN mkdir -p /overlay_ws/src
WORKDIR /overlay_ws
COPY ./${REPO}/ ./src/${REPO}/
RUN source /upstream_ws/install/setup.bash \
    && rosdep install --from-paths src --ignore-src --rosdistro ${ROS_DISTRO} -y
# && colcon build --symlink-install

# Copy the VSCode settings
COPY ./.vscode /overlay_ws/.vscode

# Set up the entrypoint
COPY ./docker/entrypoint.sh /
ENTRYPOINT [ "/entrypoint.sh" ]
#####################
# Development Image #
#####################
FROM overlay as dev

# Dev container arguments
ARG USERNAME=devuser
ARG UID=${UID}
ARG GID=${GID}

# Install extra tools for development
RUN --mount=type=cache,target=/var/cache/apt,id=apt \
    apt-get update && apt-get install -y --no-install-recommends \
    gdb gdbserver nano \
    git \
    openssh-client \
    python3-pip \
    vim \
    wget \
    && rm -rf /var/lib/apt/lists/*

# install developer tools
RUN python3 -m pip install --no-cache-dir \
    pre-commit==3.0.4

# Create new user and home directory
RUN groupadd --gid $GID $USERNAME \
    && useradd --uid ${GID} --gid ${UID} --create-home ${USERNAME} \
    && echo ${USERNAME} ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/${USERNAME} \
    && chmod 0440 /etc/sudoers.d/${USERNAME} \
    && mkdir -p /home/${USERNAME} \
    && chown -R ${UID}:${GID} /home/${USERNAME}

# Set the ownership of the overlay workspace to the new user
RUN chown -R ${UID}:${GID} /overlay_ws/

# Set the user and source entrypoint in the user's .bashrc file
USER ${USERNAME}
RUN echo "source /entrypoint.sh" >> /home/${USERNAME}/.bashrc

๊ธฐ๋ณธ์ ์œผ๋กœ ์šฐ๋ฆฌ๊ฐ€ ์‚ฌ์šฉํ•  docker๋Š” ์ด๋Ÿฌํ•œ ํ˜•ํƒœ๋ฅผ ๋„๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

์šฐ๋ฆฌ๋Š” ์ด dockerfile๋ฅผ ์„ธ๊ฐœ์˜ stage(Base, overlay, dev)๋กœ ๋‚˜๋ˆ„์–ด์„œ ๊ด€๋ฆฌํ•  ์˜ˆ์ •์ž…๋‹ˆ๋‹ค.

multi-stage์— ๊ด€๋ จ๋œ ๊ธ€ : docker multi-stage์— ๊ด€๋ จ๋œ ๋‚ด์šฉ์€ ์ด ๋‚ด์šฉ์„ ์ฐธ๊ณ  ๋ฐ”๋ž๋‹ˆ๋‹ค.

Base

Base stage๋Š” ROS2 ํ™˜๊ฒฝ setting์— ๊ด€๋ จ๋œ ์„ค์น˜๊ฐ€ ์ „๋ถ€ ๋‹ด๊ฒจ์ ธ์žˆ๋Š” stage์ž…๋‹ˆ๋‹ค. ์ด ๋‹จ๊ณ„์—์„œ ํ•˜๋Š” ์ผ์„ listํ™” ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

  1. ๊ธฐ๋ณธ์ ์ธ apt package ์„ค์น˜
  2. ๊ธฐ๋ณธ์ ์ธ python package ์„ค์น˜
  3. ROS2์— ๊ด€๋ จ๋œ ์ถ”๊ฐ€์ ์ธ package ์„ค์น˜
  4. upstream_ws์— ์ถ”๊ฐ€์ ์ธ ros2 package์„ค์น˜(์ด๋•Œ ํ•ด๋‹น ros2 package์— ๊ด€๋ จ๋œ ๋‚ด์šฉ์€ [dependencies.repos](https://github.com/Kim-JeongHan/ROS_dev_template/blob/master/dependencies.repos)์— ๋‹ด๊ฒจ์žˆ์Šต๋‹ˆ๋‹ค.)
  5. display ๊ณต์œ ๋•Œ ๋ฐœ์ƒํ•˜๋Š” warning์ œ๊ฑฐ
  6. source๋“ฑ๋ก(?)

์ด๋ ‡๊ฒŒ 6๊ฐ€์ง€๊ฐ€ ๋ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

๐Ÿ’ก ์ถ”๊ฐ€์ ์ธ ํ”„๋กœ์ ํŠธ ์ง„ํ–‰์ด ์žˆ์„๋•Œ, ์ด 6๊ฐ€์ง€ ํ•ด๋‹น ์‚ฌํ•ญ์ด ์žˆ๋Š” ๊ฒฝ์šฐ dockerfile์— ์ถ”๊ฐ€ํ•œ ๋’ค `feat/architecture` branch๋ฅผ ํ†ตํ•ด์„œ pull request๋ฅผ ๋ณด๋‚ด์ฃผ์‹œ๋ฉด ๋ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

overlay

์—ฌ๊ธฐ๋Š” ์šฐ๋ฆฌ๊ฐ€ ์ฃผ๋กœ ์‚ฌ์šฉํ•˜๋Š” overlay_ws์— ๊ด€๋ จ๋œ ๋‚ด์šฉ์ด ๋‹ด๊ฒจ์ ธ ์žˆ์Šต๋‹ˆ๋‹ค.

์šฐ๋ฆฌ๋Š” develop์ž‘์—…์„ ์ฃผ๋กœ overlay_ws์— ์ง„ํ–‰ํ•˜๊ฒŒ ๋ ํ…๋ฐ ์ด๋ฅผ buildํ•˜๊ณ  ํ•˜๋Š” ์ž‘์—…์ด ์ฃผ๋กœ ์—ฌ๊ธฐ์— ๋“ค์–ด๊ฐ€์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

์•„๋งˆ ํ”„๋กœ์ ํŠธ๋ฅผ ์ง„ํ–‰ํ•จ์— ์žˆ์–ด์„œ ์ด ๋ถ€๋ถ„์— ๋Œ€ํ•œ ์ˆ˜์ •์€ ๊ฑฐ์˜ ์—†์„ ๋“ฏ ์‹ถ์Šต๋‹ˆ๋‹ค.

  1. overlay_ws ๊ตฌ์„ฑ ๋ฐ build

dev

๋ณดํ†ต ์šฐ๋ฆฌ๊ฐ€ ๊ฐœ๋ฐœ์„ ์ง„ํ–‰ํ•  ๋•Œ ์‚ฌ์šฉํ•  ๋‚ด์šฉ์ด ๋‹ด๊ฒจ์žˆ์Šต๋‹ˆ๋‹ค. ํŠน์ • ๊ฐœ๋ฐœ testing์„ ํ•˜๊ณ  ์‹ถ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, apt package, python package, **์„ผ์„œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ**๋ฅผ ํ…Œ์ŠคํŠธ ํ•˜๊ณ  ์‹ถ์€ ๊ฒฝ์šฐ ์—ฌ๊ธฐ์„œ ๋จผ์ € ๋“ฑ๋กํ•ด์„œ build test๋ฅผ ์ง„ํ–‰ํ•˜์‹œ๋ฉด ๋ฉ๋‹ˆ๋‹ค.

์—ฌ๊ธฐ์— ์ถ”๊ฐ€ํ•˜์—ฌ testing์„ ์ง„ํ–‰ํ•˜๊ณ  ๊ผญ ํ•„์š”ํ•˜๊ฑฐ๋‚˜, ํ•ด๋‹น ์ž‘์—…์ด ์•ž์œผ๋กœ๋„ ํ•„์š”ํ•˜๋‹ค๋ฉด base ๋‹จ๊ณ„๋กœ ์˜ฌ๋ ค์ฃผ์‹œ๋ฉด ๋ฉ๋‹ˆ๋‹ค.

๋ณดํ†ต ๊ฐœ๋ฐœ์— ํ•„์š”ํ•œ apt, pip3์— ๋Œ€ํ•œ ๋‚ด์šฉ์ด ์—ฌ๊ธฐ์— ๋‹ด๊ฒจ์ ธ ์žˆ์Šต๋‹ˆ๋‹ค.

  1. container arguement
  2. ๊ฐœ๋ฐœ์— ํ•„์š”ํ•œ ์ถ”๊ฐ€์ ์ธ tool
  3. ๊ฐœ๋ฐœ์— ํ•„์š”ํ•œ python ํŒจํ‚ค์ง€
  4. ๊ฐœ๋ฐœ์— ํ•„์š”ํ•œ home directory group์„ค์ • ๋ฐ ๊ถŒํ•œ ์„ค์ •
  5. ๊ฐœ๋ฐœ์— ํ•„์š”ํ•œ bashrc ์„ค์ •

docker-compose.yaml์€ docker์—์„œ docker build, docker run๋“ฑ GUI์ฐจ์›์—์„œ ์ง€์›ํ•˜๋˜ ๊ธฐ๋Šฅ์„ ๋” ์‰ฝ๊ฒŒ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด ๋งŒ๋“  ์ถ”๊ฐ€ ๊ธฐ๋Šฅ ์ž…๋‹ˆ๋‹ค.

๊ด€๋ จ๋œ ๋‚ด์šฉ์ด ๊ถ๊ธˆํ•˜์‹œ๋‹ค๋ฉด ํ•ด๋‹น ๋งํฌ๋“ค์„ ์ฝ์–ด๋ณด๊ธธ ๋ฐ”๋ž๋‹ˆ๋‹ค.

docker compose build : https://engineer-mole.tistory.com/221

docker compose : https://docs.docker.com/compose/

# Usage:
#
# To build the images:
#   docker compose build
#
# To start up a specific service by name:
#   docker compose up <service_name>
#
# To open an interactive shell to a running container:
#   docker exec -it <container_name> bash
version: "3.9"
services:
  # Base image containing dependencies.
  base:
    build:
      context: .
      dockerfile: docker/Dockerfile
      args:
        - REPO=${REPO}
        - ROS_DISTRO=${ROS_DISTRO}
      target: base
    image: ${REPO}-base:${ROS_DISTRO}
    # Interactive shell
    stdin_open: true
    tty: true
    # Networking and IPC for ROS 2
    network_mode: host
    ipc: host
    # Needed to display graphical applications
    privileged: True
    environment:
      # Allows graphical programs in the container.
      - DISPLAY=${DISPLAY}
      - QT_X11_NO_MITSHM=1
      - NVIDIA_DRIVER_CAPABILITIES=all
      # Needed to run ROS 2 nodes
      - ROS_DOMAIN_ID=${ROS_DOMAIN_ID:-0}
      - TERM=xterm-256color
    volumes:
      # Allows graphical programs in the container.
      - /tmp/.X11-unix:/tmp/.X11-unix:rw
      - ${XAUTHORITY:-$HOME/.Xauthority}:/root/.Xauthority
      # Mount devices and configuration files
      - /dev:/dev
      # Mount ssh keys and git config
      - ~/.ssh:${HOME}/.ssh:ro
      - ~/.gitconfig:${HOME}/.gitconfig:ro
      # Mount group and passwd files for user permissions
      - /etc/group:/etc/group:ro
      - /etc/passwd:/etc/passwd:ro
      - /etc/shadow:/etc/shadow:ro
  # Overlay image containing the example source code.
  overlay:
    extends: base
    image: ${REPO}-overlay:${ROS_DISTRO}
    build:
      context: .
      dockerfile: docker/Dockerfile
      target: overlay

  # Developer container
  dev:
    extends: overlay
    image: ${REPO}-dev:${ROS_DISTRO}
    build:
      context: .
      dockerfile: docker/Dockerfile
      target: dev
      args:
        - UID=${UID:-1000}
        - GID=${UID:-1000}
        - USERNAME=${USERNAME:-devuser}
    volumes:
      # Mount the source code
      - ./${REPO}:/overlay_ws/src/${REPO}:rw
      # Mount colcon build artifacts for faster rebuilds
      - ./.colcon/build/:/overlay_ws/build/:rw
      - ./.colcon/install/:/overlay_ws/install/:rw
      - ./.colcon/log/:/overlay_ws/log/:rw
      # Mount docker directory for faster edits to Dockerfile
      - ./docker:/overlay_ws/docker:rw
      # Mount .devcontainer directory for faster edits to devcontainer.json
      - ./.devcontainer:/overlay_ws/.devcontainer:rw
    user: ${USERNAME:-devuser}
    container_name: ${USER}-${REPO}-dev
    command: bash -c "bash"

์•„๊นŒ๋ž‘ ๋น„์Šทํ•œ ๋А๋‚Œ์ž…๋‹ˆ๋‹ค. ์—ฌ๊ธฐ๋„ base, overlay, dev ์„ธ ๊ฐ€์ง€๋กœ ํฌ๊ฒŒ ๊ตฌ์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค.

์ฃผ์˜ ๊นŠ๊ฒŒ ์ƒ๊ฐ ํ•ด์•ผ ๋  ๋ถ€๋ถ„์€ base์— ๋‚ด์šฉ์„ overlay๋Š” ์ƒ์†์„ ๋ฐ›๊ณ  ์žˆ๊ณ , dev๋Š” overlay๋ฅผ ์ƒ์† ๋ฐ›๊ณ  ์žˆ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

base

dockerfile base stage๋ฅผ buildํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

์‚ฌ์‹ค ์—ฌ๊ธฐ๋„ dockerfile์—์„œ ์ถ”๊ตฌํ•˜๋Š” ๋ฐฉํ–ฅ์„ฑ๊ณผ ๋˜‘๊ฐ™์Šต๋‹ˆ๋‹ค. base, overlay,dev์—์„œ ๊ณตํ†ต์ ์œผ๋กœ ์ ์šฉ ๋˜์–ด์•ผ ํ•˜๋Š” ๊ฒƒ๋“ค์€ ์ „๋ถ€ base์ชฝ์— ๋“ค์–ด๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

  • ํ†ต์‹ ์„ ์œ„ํ•œ setting
  • volume mount
    • display๋ฅผ ์œ„ํ•œ mount
    • permission๊ณต์œ ๋ฅผ ์œ„ํ•œ mount
    • device ๊ณต์œ ๋ฅผ ์œ„ํ•œ mount

overlay

๋ณ„ ๋‚ด์šฉ์€ ์—†์Šต๋‹ˆ๋‹ค. dockerfile overlay stage๋ฅผ buildํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

dev

dockerfile dev stage๋ฅผ buildํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

volume mount๊ด€๋ จ๋œ ๋‚ด์šฉ์€ ์šฐ๋ฆฌ๊ฐ€ ํ”„๋กœ์ ํŠธ๋ฅผ ์ง„ํ–‰ํ•˜๊ธฐ ์œ„ํ•œ ๋‚ด์šฉ์„ ์ฃผ๋กœ ๋‹ค๋ฃจ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. container์™€ local ํ™˜๊ฒฝ์„ mount์‹œ์ผœ์„œ ์ข€ ๋” ์‰ฝ๊ฒŒ ํ”„๋กœ์ ํŠธ๋ฅผ ์ง„ํ–‰ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋„์™€์ค๋‹ˆ๋‹ค.

  • volume mount
    • source code
    • .colcon์•ˆ์— ์žˆ๋Š” build, install, logํŒŒ์ผ์„ container์•ˆ์— ์žˆ๋Š” workspace์™€ mountํ•˜์—ฌ container๋ฅผ ๋‚˜๊ฐ€๋”๋ผ๋„ ๋นŒ๋“œํ•œ ํŒจํ‚ค์ง€๋ฅผ ์žฌ ๋นŒ๋“œํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.
    • dockerfile๋ฅผ mountํ•˜์—ฌ ๋‚ด๋ถ€ container์—์„œ dockerfile๋ฅผ ์‰ฝ๊ฒŒ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค๋‹ˆ๋‹ค.
    • .devcontainer๋ฅผ mountํ•˜์—ฌ ๋‚ด๋ถ€ container์—์„œ dockerfile๋ฅผ ์‰ฝ๊ฒŒ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค๋‹ˆ๋‹ค.
    • ์ถ”๊ฐ€์ ์œผ๋กœ ์ˆ˜์ •์ด ์žˆ์„ ์˜ˆ์ •์ž…๋‹ˆ๋‹ค.

์ด ํŒŒ์ผ์€ docker-compose๊ธฐ๋Šฅ์„ ์ˆ˜ํ–‰ํ•  ๋•Œ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๋„ฃ์–ด์ค„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋˜ํ•œ vscode extension์™€๋„ ๊ด€๋ จ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

REPO=gole
ROS_DISTRO=humble
PYTHONPATH=src:install/lib/python3.10/site-packages

.pre-commit-config๊ด€๋ จํ•œ ๋‚ด์šฉ์ž…๋‹ˆ๋‹ค. ์‚ฌ์‹ค ์ด ๋ถ€๋ถ„์€ ์ž์„ธํ•˜๊ฒŒ ํ•  ๋‚ด์šฉ์ด ๋”ฐ๋กœ ์—†๊ณ  ์„ธ๋ฏธ๋‚˜ ํ–ˆ๋˜ ๋‚ด์šฉ์„ ์ฐธ๊ณ ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

pre-commit ๊ฐ„๋‹จ ์„ธ๋ฏธ๋‚˜

์ค‘์š”ํ•œ ๊ฒƒ์€ git clone์„ ์ง„ํ–‰ํ•œ ๋‹ค์Œ์— pre-commit install ๋ฐ˜๋“œ์‹œ ํ•ด์ค˜์•ผ ํ™œ์„ฑํ™” ๋œ๋‹ค๋Š” ๊ฒƒ ์ž…๋‹ˆ๋‹ค.

.devcontainer

devcontainer.json

์ด๋Š” vscode๋ฅผ ํ•ด๋‹น directory์—์„œ ํ‚ค๋ฉด ์ž๋™์œผ๋กœ docker-composeํŒŒ์ผ์— ๋”ฐ๋ผ build๋ฅผ ์ง„ํ–‰ํ•˜๊ณ , ๊ฐœ๋ฐœ container๋ฅผ ๊ตฌ์„ฑํ• ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋Š” jsonํŒŒ์ผ์ž…๋‹ˆ๋‹ค. ์ด๋•Œ local vscode extension์ค‘ ์„ ํƒ์ ์œผ๋กœ ๊ผญ ํ•„์š”ํ•œ ๋ถ€๋ถ„์„ ๊ณต์œ ํ•  ์ˆ˜ ์žˆ๊ฒŒ extension์ถ”๊ฐ€๋ฅผ ํ•ด ๋†“์•˜์Šต๋‹ˆ๋‹ค.

์ด ์™ธ์— ์ถ”๊ฐ€ํ–ˆ์œผ๋ฉด ํ•˜๋Š” vscode extension๊ฐ™์€ ๊ฒฝ์šฐ updateํ•ด์ฃผ์‹œ๋ฉด pull-request๋ฅผ ํ†ตํ•ด updateํ•˜๊ณ  ์—ฌ๊ธฐ์„œ ๊ณต์œ ํ•ด์ฃผ์—ˆ์œผ๋ฉด ํ•ฉ๋‹ˆ๋‹ค.

// See https://aka.ms/vscode-remote/devcontainer.json for format details.
{
    "dockerComposeFile": "../docker-compose.yaml",
    "service": "dev",
    "workspaceFolder" : "/overlay_ws",
	// Set *default* container specific settings.json values on container create.
	"customizations": {
		"vscode": {
			"extensions": [
				"althack.ament-task-provider",
				"betwo.b2-catkin-tools",
				"DotJoshJohnson.xml",
				"ms-azuretools.vscode-docker",
				"ms-iot.vscode-ros",
				"ms-python.python",
				"ms-vscode.cpptools",
				"redhat.vscode-yaml",
				"smilerobotics.urdf",
				"streetsidesoftware.code-spell-checker",
				"twxs.cmake",
				"yzhang.markdown-all-in-one",
				"zachflower.uncrustify"
			]
		}
	}
}

์ €๋„ ํ•˜๋‚˜ํ•˜๋‚˜์˜ extension์— ๋Œ€ํ•œ ๋‚ด์šฉ์„ ์•Œ์ง€ ๋ชปํ•˜์—ฌ ์„ค๋ช…์€ ์ƒ๋žตํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

๐Ÿ’ก ๋งŒ์•ฝ ํ”„๋กœ์ ํŠธ๋ฅผ ์ง„ํ–‰ํ•˜๋‹ค ๊ณต์œ ํ•˜๊ณ  ์‹ถ์€ extension์ด ์žˆ์œผ๋ฉด ์ถ”๊ฐ€ํ•œ ๋’ค ๊ฐ„๋‹จํ•œ ์„ค๋ช…์„ ์จ์ฃผ์‹œ๋ฉด ๊ฐ์‚ฌํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

.vscode

launch.json

debug๋ฐ ์‹คํ–‰ํŒŒ์ผ์˜ ์‹คํ–‰์„ ์œ„ํ•ด settingํ•ด๋†“์€ ๋ถ€๋ถ„์ž…๋‹ˆ๋‹ค.

F5๋ฅผ ํ†ตํ•ด ์‰ฝ๊ฒŒ debugํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

image

์ €ํฌ๊ฐ€ ์ฃผ๋กœ ์‚ฌ์šฉํ•  debug์ž…๋‹ˆ๋‹ค.

๋”ฐ๋กœ ์‹œ๊ฐ„์ด ์ƒ๊ธด๋‹ค๋ฉด vscode extension debugging๋ฅผ ์ฐธ๊ณ ํ•˜์—ฌ ์ถ”๊ฐ€์ ์œผ๋กœ ์„ค๋ช…ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

settings.json

์ด ๋ถ€๋ถ„์€ ๊ฐœ๋ฐœ container์—์„œ python, yaml, xml, c++๋“ฑ์„ ํŽธ์ง‘ํ•  ๋•Œ ์ข€ ๋” ํŽธ๋ฆฌํ•˜๊ฒŒ ๋ณผ ์ˆ˜ ์žˆ๊ฒŒ ํ•˜๋Š” ์„ค์ • ์ •๋ณด๋ฅผ ํฌํ•จํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ํ•ด๋‹น ๋ถ€๋ถ„์ด ๋งˆ์Œ์— ๋“ค์ง€ ์•Š๋Š”๋‹ค๋ฉด ์ˆ˜์ •ํ•˜๊ฑฐ๋‚˜ ํ•ด๋„ ๋ฉ๋‹ˆ๋‹ค.

{
    "editor.tabSize": 8,
    "editor.rulers": [
        100
    ],
    "files.associations": {
        "*.repos": "yaml",
        "*.world": "xml",
        "*.xacro": "xml"
    },
    ///////////////////////////////////////////////////////
    //if you don't use humble, comment out the next line
    "python.analysis.extraPaths": [
        "/opt/ros/humble/lib/python3.10/site-packages/"
    ],
    // // Autocomplete from ros python packages
    "python.autoComplete.extraPaths": [
        "/opt/ros/humble/lib/python3.10/site-packages/"
    ],
    // // Environment file lets vscode find python files within workspace
    "python.envFile": "${workspaceFolder}/.env",
    // Use the system installed version of autopep8
    "python.formatting.autopep8Path": "/usr/bin/autopep8",
    "python.formatting.autopep8Args": [
        "--max-line-length=100"
    ],
    "C_Cpp.default.intelliSenseMode": "linux-gcc-x86",
    "C_Cpp.formatting": "disabled",
    "uncrustify.configPath.linux": "/opt/ros/humble/lib/python3.10/site-packages/ament_uncrustify/configuration/ament_code_style.cfg",
    "[cpp]": {
        "editor.defaultFormatter": "zachflower.uncrustify"
    },
    //comment out this line if you don't use humble
    ///////////////////////////////////////////////////////
    "search.exclude": {
        "**/node_modules": true,
        "**/bower_components": true,
        "**/*.code-search": true,
        "**/build": true,
        "**/install": true,
        "**/log": true
    },
    "cSpell.words": [
        "RTPS",
        "athackst",
        "autopep",
        "cmake",
        "cppcheck",
        "cpplint",
        "DCMAKE",
        "deque",
        "devcontainer",
        "ints",
        "noqa",
        "pytest",
        "rclcpp",
        "rclpy",
        "repos",
        "rosdep",
        "rosdistro",
        "rosidl",
        "RTPS",
        "uncrustify",
        "Wextra",
        "Wpedantic",
        "xmllint"
    ],
    "cSpell.allowCompoundWords": true,
    "cSpell.ignorePaths": [
        "**/package-lock.json",
        "**/node_modules/**",
        "**/vscode-extension/**",
        "**/.git/objects/**",
        ".vscode",
        ".vscode-insiders",
        ".devcontainer/devcontainer.json"
    ]
}

tasks.json

๋‚˜๋งŒ์˜ custom ๊ณต์‹์„ ๋งŒ๋“œ๋Š” ๊ณณ ์ž…๋‹ˆ๋‹ค.

.vscode์˜ tasks.json ์ดํ•ดํ•ด๋ณด๊ธฐ

Ctrl+alt+p ๋ฅผ ๋ˆ„๋ฅด๊ณ  tasks๋ฅผ ๊ฒ€์ƒ‰ํ•˜๋ฉด ๋ณธ์ธ์ด ์ถ”๊ฐ€ํ•ด๋†“์€ tasks์™€ ๊ด€๋ จ๋œ ์ถ”๊ฐ€์ ์ธ ์ž๋™ ๋‹จ์ถ•ํ‚ค๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

image

Run task์— build, clean, debug๋“ฑ ๋‹ค์–‘ํ•œ ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•ด๋†“์•˜์Šต๋‹ˆ๋‹ค. ํด๋ฆญํ•˜๊ฒŒ ๋˜๋ฉด ์ž๋™์œผ๋กœ ํ•ด๋‹น๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฐ‘์—์„œ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ธฐ๋Šฅ์—๋Œ€ํ•œ ์„ค๋ช…์„ ํ•˜๋‚˜์”ฉ ์„ค๋ช…ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

build

./docker/build.sh๋ฅผ ์‹คํ–‰์‹œํ‚ต๋‹ˆ๋‹ค.

#!/bin/bash
set -e

# Choose build
# --symlink-install : symlink the package into the install space
# --merge-install : merge all packages into one install space

# Set the default build type
BUILD_TYPE=RelWithDebInfo
colcon build \
        --symlink-install \
        --cmake-args "-DCMAKE_BUILD_TYPE=$BUILD_TYPE" "-DCMAKE_EXPORT_COMPILE_COMMANDS=On" \
        -Wall -Wextra -Wpedantic

build --symlink-install๊ณผ --merge-install ๋ฐฉ์‹์ค‘ ์„ ํƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ €ํฌ๋Š” ์ฃผ๋กœ --symlink-install ๋ฐฉ์‹์„ ์ฃผ๋กœ ์„ ํƒํ•ด์„œ ์‚ฌ์šฉํ•  ์˜ˆ์ •์ž…๋‹ˆ๋‹ค.

DCMAKE_BUILD_TYPE๋ฅผ build๋กœ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค.

clean

๋นŒ๋“œ๋œ ํŒŒ์ผ์„ ์ •๋ฆฌํ•˜๊ณ  ์ดˆ๊ธฐ ์ƒํƒœ๋กœ ๋˜๋Œ๋ฆฌ๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. **colcon**์„ ์‚ฌ์šฉํ•˜์—ฌ ๋นŒ๋“œ๋œ ํŒŒ์ผ์„ ์ œ๊ฑฐํ•จ์œผ๋กœ์จ ๋‹ค์‹œ ๋นŒ๋“œํ•  ๋•Œ ๊น”๋”ํ•˜๊ฒŒ ์žฌ ๋นŒ๋“œํ• ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. "clean" ์ž‘์—…์„ ์‹คํ–‰ํ•˜๋ฉด ํ”„๋กœ์ ํŠธ์˜ ์ž„์‹œ ๋ฐ ์ƒ์„ฑ๋œ ํŒŒ์ผ์„ ์ •๋ฆฌํ•˜์—ฌ ์ฝ”๋“œ๋ฅผ ๊ด€๋ฆฌํ•˜๊ธฐ ์ข€ ๋” ์‰ฝ๊ฒŒ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

colcon build --cmake-target clean

debug

./docker/build.sh๋ฅผ ์‹คํ–‰์‹œํ‚ต๋‹ˆ๋‹ค.

DCMAKE_BUILD_TYPE๋ฅผ debug๋กœ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค.

test

colcon test๋ฅผ ์ž‘๋™์‹œํ‚ต๋‹ˆ๋‹ค.

ํ•ด๋‹น ๋ช…๋ น์€ overlay_ws์—์„œ ์ž‘๋™์‹œํ‚ค๋Š” ๊ฒƒ์„ ์ถ”์ฒœํ•ฉ๋‹ˆ๋‹ค.

fix, uncrustify

์šฐ๋ฆฌ๋Š” uncrustify์—์„œ ์ •์˜๋œ ๋ฐฉ์‹์˜ formatting๋ฐฉ์‹์„ ์‚ฌ์šฉํ•  ์˜ˆ์ •์ž…๋‹ˆ๋‹ค.

https://github.com/uncrustify/uncrustify

"uncrustify"๋Š” ์ฝ”๋“œ ์Šคํƒ€์ผ์„ ์žฌ์ •๋ ฌํ•˜๊ณ  ์ผ๊ด€์„ฑ ์žˆ๊ฒŒ ์œ ์ง€ํ•˜๊ธฐ ์œ„ํ•œ code formatter ๋ฐ linter์ž…๋‹ˆ๋‹ค. ์ฝ”๋“œ ํŒŒ์ผ์˜ ๋“ค์—ฌ์“ฐ๊ธฐ, ๊ณต๋ฐฑ, ์ค„ ๋ฐ”๊ฟˆ ๋“ฑ์„ ์ผ๊ด€์„ฑ ์žˆ๊ฒŒ ๋ณ€๊ฒฝํ•˜์—ฌ ์ผ๊ด€๋œ ์ฝ”๋“œ ๊ทœ์น™์„ ์œ ์ง€ํ•˜๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค.

linter์˜ ๊ฐœ๋…์— ๋Œ€ํ•œ ๊ด€๋ จ๊ธ€์„ ์ฒจ๋ถ€ํ–ˆ์Šต๋‹ˆ๋‹ค.

linter๋ฅผ ์ด์šฉํ•œ ์ฝ”๋”ฉ์Šคํƒ€์ผ๊ณผ ์—๋Ÿฌ ์ฒดํฌํ•˜๊ธฐ

ROSํ”„๋กœ๊ทธ๋ž˜๋ฐ ๊ทœ์น™์— ๋Œ€ํ•œ ๊ฐ„๋‹จํ•œ ์ž๋ฃŒ๋ฅผ ์ฒจ๋ถ€ํ–ˆ์Šต๋‹ˆ๋‹ค.

Ros ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๊ทœ์น™

fix ์ฃผ๋กœ ์ฝ”๋“œ๋ฅผ ์žฌ์ •๋ ฌ ๋ฐ ๊ฐ€๋…์„ฑ์„ ๋†’์ด๋Š”๋ฐ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

uncrustify ์ฃผ๋กœ ์ฝ”๋“œ style ๊ฒ€์‚ฌ ๋ฐ code linting์„ ํ†ตํ•ด์„œ ์ฝ”๋“œ ํ˜•์‹๋ฌธ์ œ๋ฅผ ์ฐพ์•„๋ƒ…๋‹ˆ๋‹ค.

๋‘˜๋‹ค optionalํ•œ ๋ถ€๋ถ„์ž…๋‹ˆ๋‹ค.

lint all

๋ณธ์ธ์ด ์ˆ˜์ •ํ•˜๊ณ  ์žˆ๋Š” c++, python ๋‹จ์ผ ํŒŒ์ผ์„ ๊ฒ€์‚ฌํ•˜๊ณ  ์‹ถ์„ ๋•Œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. code linting์„ ํ†ตํ•ด์„œ ํ˜•์‹๋ฌธ์ œ๋ฅผ ์ฐพ์•„์„œ ์ˆ˜์ •ํ•ด์ค๋‹ˆ๋‹ค.

install dependencies

ํ•ด๋‹น package๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ์œ„ํ•œ dependencies๋ฅผ ์ž๋™์œผ๋กœ ์ฐพ์•„์„œ ์„ค์น˜ํ•ด์ค๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด์„œ ์„ค์น˜๋˜๋Š” ํŒŒ์ผ๋“ค์€ /opt/ros/humble ์•ˆ์—์„œ ์ฐพ์•„๋ณด๋ฉด ์žˆ์Šต๋‹ˆ๋‹ค.

new ament_python package, new ament_cmake package

์ƒˆ๋กœ์šด python์ด๋‚˜ c++ ํŒจํ‚ค์ง€๋ฅผ ๋งŒ๋“ค๋•Œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

์œ„์น˜๋Š” src/gole์— ์ž๋™์œผ๋กœ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค.

c_cpp_properties.json

๋ณด๋‹ค๋” ํšจ๊ณผ์ ์ธ c++๊ฐœ๋ฐœ์„ ์œ„ํ•œ ํ™˜๊ฒฝ์„ค์ •์ž…๋‹ˆ๋‹ค.