# 환경 변수 설정 및 워크스페이스 구조

#### ROS2 Humble 환경 변수 개요

* ROS2 Humble 버전을 활용하기 위해서는 먼저 ROS2가 설치된 경로를 올바르게 설정해야 한다. Ubuntu 환경에서 apt 패키지로 설치했다면 일반적으로 `/opt/ros/humble` 디렉터리에 설치된다.
* ROS2와 관련된 환경 변수들은 ROS1과 달리

  `$ROS_MASTER_URI` 대신 `$ROS_DISTRO`, `$ROS_VERSION`, `$AMENT_PREFIX_PATH`

  등으로 구성된다.

  * `$ROS_VERSION`은 ROS의 주요 버전을 나타내고, 2라면 ROS2를 의미한다.
  * `$ROS_DISTRO`는 현재 사용 중인 ROS 배포판 이름이다. 예: `humble`
  * `$AMENT_PREFIX_PATH`는 ament 빌드 시스템이 패키지를 찾는 경로를 의미한다.
* 대부분의 환경 변수는 ROS2 설치 경로 안의 `setup.bash`를 실행함으로써 자동으로 설정된다. 예를 들어:

```bash
source /opt/ros/humble/setup.bash
```

* 어떤 셸을 사용하는지에 따라 `.bashrc`, `.zshrc` 등에 위 명령어를 추가하여 자동으로 설정될 수 있도록 한다.

#### 환경 변수를 설정하는 이유

* 여러 ROS2 버전을 동시에 설치해 사용할 경우에는 특정 버전을 사용하기 위해 해당 버전의 `setup.bash`를 소스해야 한다.
* `$AMENT_PREFIX_PATH`, `$COLCON_PREFIX_PATH` 등이 명시적으로 설정되어 있지 않으면 ROS2의 빌드 및 실행 시 패키지 경로가 올바르게 인식되지 않을 수 있다.
* `$PATH`에는 ROS2 실행 파일을 찾기 위한 경로가 등록되고, `$LD_LIBRARY_PATH`에는 ROS2 관련 라이브러리를 찾기 위한 경로가 등록된다.

#### ROS2 개발용 워크스페이스 구성

* ROS2에서는 기본적으로 `colcon` 빌드 툴을 사용하여 워크스페이스를 구성하고, `CMakeLists.txt`와 `package.xml`을 통해서 패키지 정보를 관리한다.
* 일반적인 ROS2 워크스페이스 구조는 아래와 같이 크게 세 가지 디렉터리를 포함한다.
  1. `src` : 패키지 소스 코드가 위치
  2. `build` : `colcon build` 이후 생성되는 빌드 산출물
  3. `install` : 빌드 이후 실행할 수 있는 패키지 설치물
* 워크스페이스 내 `src` 디렉터리에는 여러 개의 ROS2 패키지를 구성할 수 있으며, 각각의 패키지는 아래와 같이 구성된다.
  * `package.xml`: 패키지 매니페스트, 의존성 및 패키지 정보를 명시
  * `CMakeLists.txt`: 빌드 설정 파일, ament\_cmake 사용 시 필수
  * 소스 코드(.cpp, .h, .py 등)와 기타 리소스(.msg, .srv 등)

#### 워크스페이스 내부 구조 예시

아래는 mermaid를 활용하여 ROS2 워크스페이스 내부 구조를 간략히 나타낸 예이다.

{% @mermaid/diagram content="flowchart TB
A\["\~/ros2\_ws"] --> B\["src"]
A --> C\["build"]
A --> D\["install"]

```
B --> E["my_package"]
E --> F["package.xml"]
E --> G["CMakeLists.txt"]
E --> H["소스 코드, 메시지, 서비스 파일 등"]" %}
```

#### 오버레이(Overlay) 워크스페이스

* ROS2에서는 다른 워크스페이스 위에 또 다른 워크스페이스를 덧씌우는(overlay) 방식으로 다단계 환경 구성이 가능하다.
* 예를 들어, `/opt/ros/humble`에 설치된 표준 ROS2 패키지 위에 `~/ros2_ws`에서 개발한 패키지를 올린 다음, 또 다른 워크스페이스인 `~/ros2_additional_ws`를 통해 추가 기능을 개발할 수 있다.
* 오버레이 구조에서 핵심은 새로운 워크스페이스를 빌드하고, 해당 워크스페이스의 `setup.bash` 혹은 `local_setup.bash`를 소스(`source`)함으로써 기존 환경 변수를 유지하면서도 추가된 패키지나 수정된 패키지를 우선 적용하는 것이다.

```bash
# 기본 ROS2 환경 설정
source /opt/ros/humble/setup.bash

# 1차 개발 워크스페이스 오버레이
cd ~/ros2_ws
colcon build
source install/setup.bash

# 2차 개발 워크스페이스 오버레이
cd ~/ros2_additional_ws
colcon build
source install/local_setup.bash
```

* 위와 같은 과정을 통해 여러 계층의 워크스페이스를 운영할 수 있으며, 빌드 결과물을 개별적으로 관리하면서도 기존 ROS2 기능을 그대로 활용할 수 있다.

#### setup.bash vs local\_setup.bash

* `setup.bash`는 ROS2 워크스페이스 전체를 활용하기 위한 전반적 환경 변수 설정 스크립트다.
* `local_setup.bash`는 해당 패키지(혹은 해당 워크스페이스)의 환경 변수를 국소적으로 설정하는 스크립트다.
  * 예를 들어 다른 패키지가 충돌되는 환경 변수를 수정해놓았다면, `local_setup.bash`를 통해서 현재 패키지에 필요한 설정만 다시 덮어쓸 수 있다.
* 일반적으로 상위 설치 경로에 포함된 모든 내용을 포함하려면 `setup.bash`를, 해당 디렉터리에만 적용되는 설정을 원한다면 `local_setup.bash`를 사용한다.

#### 환경 변수 우선순위

* 여러 워크스페이스를 오버레이할 때, 패스 설정은 순차적으로 뒤에서 소스한 워크스페이스가 우선순위를 갖는다.
  * 예: `$PATH`, `$AMENT_PREFIX_PATH`, `$LD_LIBRARY_PATH` 등은 소스 순서에 따라 패키지 로딩 순서가 달라진다.
* 패키지 버전이 충돌될 경우, 마지막으로 소스된 워크스페이스 내 패키지가 우선 적용되므로 주의가 필요하다.
* 환경 변수를 확인하고자 할 때에는 다음 명령어를 활용해 볼 수 있다:

```bash
printenv | grep ROS
```

#### 빌드 옵션과 환경 변수

* colcon 빌드 시 다양한 옵션을 지정할 수 있는데, 이때도 환경 변수가 영향을 미친다.
  * 예: `colcon build --symlink-install` 옵션은 라이브러리 파일을 링크 형태로 설치하여 수정 시 즉시 반영되도록 만든다.
  * `$AMENT_PREFIX_PATH`가 잘못 설정되어 있으면 colcon이 의존 패키지를 찾지 못할 수 있다.
* 빌드 환경 변수를 확인하기 위해서는 `colcon build --event-handlers console_direct+` 명령어와 같은 이벤트 핸들러를 사용해서 빌드 과정을 좀 더 자세히 확인할 수 있다.

#### 자주 사용하는 ROS2 환경 변수

`$ROS_DOMAIN_ID`:

* ROS2 통신에서 고유 도메인 식별자를 설정한다. 기본값은 `0`이지만, 여러 팀이 공유 네트워크에서 ROS2를 동시에 사용하거나, 독립적인 네트워크 트래픽 격리가 필요할 경우 값을 다르게 설정한다.
* 예:

```bash
export ROS_DOMAIN_ID=42
```

`$ROS_LOCALHOST_ONLY`:

* 로컬 호스트(Loopback) 통신만 가능하도록 제한하는 변수다. `1`로 설정하면 같은 머신 안에서만 노드 통신을 수행할 수 있다.
* 예:

```bash
export ROS_LOCALHOST_ONLY=1
```

`$RMW_IMPLEMENTATION`:

* ROS2가 사용할 DDS(데이터 분산 서비스) RMW(Robot Middleware) 구현체를 지정한다. 기본값은 FastDDS(Fast-RTPS) 또는 CycloneDDS가 될 수 있다.
* 예:

```bash
export RMW_IMPLEMENTATION=rmw_fastrtps_cpp
```

#### 다양한 셸에서의 환경 변수 설정

* 기본적으로 `.bashrc` 를 활용하는 Ubuntu 표준 환경이라면 다음처럼 설정 가능하다.

```bash
echo "source /opt/ros/humble/setup.bash" >> ~/.bashrc
```

* Zsh를 사용하는 환경이라면 다음처럼 설정 가능하다.

```bash
echo "source /opt/ros/humble/setup.zsh" >> ~/.zshrc
```

* Fish 셸을 사용한다면 ROS2에서 제공하는 `setup.fish` 스크립트를 불러와야 한다.

```bash
source /opt/ros/humble/setup.fish
```

* 각각의 셸 특성에 따라 환경 변수가 등록되는 방식이 다를 수 있으므로, 여러 셸을 병행해서 사용 시 충돌을 일으키지 않도록 주의해야 한다.

#### 환경 변수 확인 및 재설정

* ROS2 동작 중에 환경 변수 변경이 필요한 경우가 생길 수 있다. 이때는 설정값 변경 후 다시 source 하는 과정이 필요하다.
* 예:

```bash
# 기존 도메인 ID를 0에서 5로 변경
export ROS_DOMAIN_ID=5
# 수정된 값 반영을 위해 다시 setup.bash 소스
source /opt/ros/humble/setup.bash
```

* 변경 후에는 `printenv | grep ROS` 또는 `env | grep ROS` 명령어로 재설정이 올바르게 반영되었는지 확인한다.

#### 환경 변수 충돌과 해결

* 여러 워크스페이스를 오버레이하거나, 다른 ROS2 버전(예: Galactic, Foxy)과 혼용할 때 환경 변수가 충돌해 빌드나 실행이 실패하는 경우가 있다.
  * 잘못된 `$AMENT_PREFIX_PATH`로 인해 특정 패키지를 찾지 못한다.
  * `$RMW_IMPLEMENTATION`이 서로 다른 버전을 지정한다.
  * `$LD_LIBRARY_PATH`가 누락되어 ROS2 실행 파일이 필요한 라이브러리를 찾지 못한다.
* 가장 쉬운 해결책은 문제 발생 시 다시 한 번 ROS2 Humble의 기본 `setup.bash`를 소스하고, 원하는 워크스페이스 순으로 순차적으로 소스하여 환경 변수를 재설정하는 것이다.

#### Docker 환경에서의 ROS2 Humble 환경 변수

* ROS2 Humble을 Docker 컨테이너로 구동할 때도, 호스트 환경과 유사하게 컨테이너 내부에서 ROS2 설치 경로를 source 해야 한다.
* 일반적으로 ROS2 Humble 기반 이미지를 사용하거나, Dockerfile을 직접 작성하는 식으로 환경을 구성한다.

```dockerfile
FROM ubuntu:22.04

# 의존성 패키지 설치
RUN apt-get update && apt-get install -y \
    curl gnupg lsb-release

# ROS2 Humble 설치 (예시)
RUN apt-get update && apt-get install -y ros-humble-desktop

# 환경 변수 및 setup.bash 반영
RUN echo "source /opt/ros/humble/setup.bash" >> /root/.bashrc
```

* 컨테이너 내부 터미널 접속 후, `.bashrc`를 다시 source 해주거나 직접 `source /opt/ros/humble/setup.bash`로 환경 변수를 불러온다.
* 여러 Docker 컨테이너로 ROS2 분산 시스템을 구성하는 경우 `$ROS_DOMAIN_ID`, `$RMW_IMPLEMENTATION` 등 중요한 환경 변수를 일관되게 설정해야 통신 충돌이 발생하지 않는다.

#### 크로스 컴파일 환경 설정 시 주의점

* 임베디드 보드나 ARM 등 x86이 아닌 다른 아키텍처 대상으로 ROS2 Humble을 빌드(크로스 컴파일)할 때, 전용 툴체인(예: `$CC`, `$CXX`)과 함께 ROS2 설치 경로가 달라질 수 있다.
* 크로스 컴파일 스크립트나 Docker 이미지를 구성할 때, `$AMENT_PREFIX_PATH` 를 타깃 아키텍처의 라이브러리와 혼동하지 않도록 주의해야 한다.
  * 필요하다면 `$AMENT_PREFIX_PATH` 내 호스트 아키텍처 경로를 제외하거나, 새로운 워크스페이스를 만들어 타깃 아키텍처만을 위한 패키지를 빌드한다.
* 임베디드 환경에서 `$ROS_DOMAIN_ID` 설정에 따라 네트워크 트래픽이 제한될 수 있으므로, 시스템 상황(네트워크 대역폭, CPU 리소스 등)을 고려하여 적절히 설정한다.
