임베디드 리눅스 Ubuntu 22.04 LTS 환경에서 ROS2 Humble 설치 및 DDS 통신 구축 배경
임베디드 리눅스 환경에서 모빌리티 및 로봇 시스템을 제어하려면 저지연 실시간 데이터 전송 아키텍처가 필수적입니다. 기존 ROS1은 마스터(Master) 노드 단일점 실패(Single Point of Failure) 문제와 실시간성 보장의 한계가 존재했습니다. ROS2 Humble Hawksbill은 Data Distribution Service(DDS) 미들웨어를 표준 분산 통신 계층으로 채택하여 이 문제를 해결했습니다. 본 문서에서는 Ubuntu 22.04 LTS 환경에서 ROS2 Humble을 설치하고, rclcpp API 기반의 Publisher와 Subscriber 노드를 작성하는 완벽한 가이드를 제공합니다.
ROS2 Humble 핵심 요약 (ROS2 Humble Quick Summary)
- 환경 및 의존성 설정 (Environment & Dependency Setup): 공식 apt 리포지토리 소스 및 UTF-8 로케일 환경 설정을 적용하여 Ubuntu 22.04 LTS 환경에 ROS2 Humble Hawksbill을 설치합니다.
- 워크스페이스 빌드 시스템 (Workspace Build System): colcon 워크스페이스 디렉터리 구조(ros2_ws/src)를 생성하고 colcon build --symlink-install 명령어로 모듈을 빌드합니다.
- 노드 IPC 패턴 (Node IPC Pattern): rclcpp API를 활용하여 C++ 기반의 Publisher 및 Subscriber 노드를 구현하고, ros2 topic echo 명령어로 프로세스 간 통신(IPC)을 검증합니다.
ROS2 Humble DDS 아키텍처 및 C++ Node 퍼블리셔 서브스크라이버 구현 분석
ROS2 DDS (Data Distribution Service) 미들웨어 동작 원리
ROS2는 기존 ROS1의 Master Node(rosmaster) 방식을 폐지하고, OMG(Object Management Group) 표준인 DDS(Data Distribution Service)를 도입했습니다. DDS는 UDP/IP 멀티캐스트 기반의 Discovery 메커니즘을 사용하여 네트워크 상의 노드를 자동 탐색합니다.
| 분류 항목 | ROS1 (Melodic/Noetic) | ROS2 (Humble Hawksbill) |
|---|---|---|
| 중앙 관리자 | XML-RPC 기반 ROS Master 필수 | Master 없음 (DDS Dynamic Discovery) |
| 통신 프로토콜 | TCPROS / UDPROS (자체 프로토콜) | RTPS (Real-Time Publish-Subscribe) via DDS |
| 실시간성 (Real-Time) | 비보장 (Linux OS 종속) | POSIX 및 RT-Patch Linux 환경 실시간 지원 |
| 품질 보증 (QoS) | 기본 TCP 송수신 옵션만 제공 | Reliability, Durability, History 등 미세 조정 가능 |
| 빌드 시스템 | catkin (CMake 기반) | colcon (ament_cmake / ament_python) |
Ubuntu 22.04 LTS ROS2 Humble 설치 절차 및 환경 변수 설정
Ubuntu 22.04 LTS 시스템에서 로케일(Locale)을 UTF-8로 설정하고 ROS2 Official Apt Repository를 추가해야 합니다.
# Locale check and update
sudo apt update && sudo apt install -y locales
sudo locale-gen en_US en_US.UTF-8
sudo update-locale LC_ALL=en_US.UTF-8 LANG=en_US.UTF-8
export LANG=en_US.UTF-8
# Software repository setup
sudo apt install -y software-properties-common
sudo add-apt-repository universe
# Add ROS2 GPG key
sudo apt update && sudo apt install -y curl
sudo curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key -o /usr/share/keyrings/ros-archive-keyring.gpg
# Add ROS2 repository to source list
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] http://packages.ros.org/ros2/ubuntu $(. /etc/os-release && echo $UBUNTU_CODENAME) main" | sudo tee /etc/apt/sources.list.d/ros2.list > /dev/null
# Install ROS2 Humble Desktop
sudo apt update
sudo apt install -y ros-humble-desktop ros-dev-tools
ROS2 Workspace 생성 및 C++ Package 구성
colcon 빌드 시스템을 위한 워크스페이스를 생성하고 ros2 pkg create 명령어로 C++ 패키지를 빌드합니다.
# Create colcon workspace
mkdir -p ~/ros2_ws/src
cd ~/ros2_ws/src
# Create ROS2 C++ package
ros2 pkg create --build-type ament_cmake demo_nodes_cpp --dependencies rclcpp std_msgs
Publisher Node 구현 예제 (publisher_node.cpp)
src/publisher_node.cpp 파일을 생성하고 다음 코드 구조를 구현합니다.
// ROS2 C++ Client Library Header
#include <chrono>
#include <memory>
#include <string>
#include "rclcpp/rclcpp.hpp"
#include "std_msgs/msg/string.hpp"
using namespace std::chrono_literals;
class MinimalPublisher : public rclcpp::Node {
public:
MinimalPublisher() : Node("minimal_publisher"), count_(0) {
// Initialize publisher with topic name and QoS history depth
publisher_ = this->create_publisher<std_msgs::msg::String>("robot_status", 10);
timer_ = this->create_wall_timer(
500ms, std::bind(&MinimalPublisher::timer_callback, this));
}
private:
void timer_callback() {
auto message = std_msgs::msg::String();
message.data = "Robot System Operational Count: " + std::to_string(count_++);
RCLCPP_INFO(this->get_logger(), "Publishing: '%s'", message.data.c_str());
publisher_->publish(message);
}
rclcpp::TimerBase::SharedPtr timer_;
rclcpp::Publisher<std_msgs::msg::String>::SharedPtr publisher_;
size_t count_;
};
int main(int argc, char * argv[]) {
rclcpp::init(argc, argv);
// Spin node to handle execution callbacks
rclcpp::spin(std::make_shared<MinimalPublisher>());
rclcpp::shutdown();
return 0;
}
Subscriber Node 구현 예제 (subscriber_node.cpp)
src/subscriber_node.cpp 파일을 작성합니다.
// ROS2 C++ Client Library Header
#include <memory>
#include "rclcpp/rclcpp.hpp"
#include "std_msgs/msg/string.hpp"
using std::placeholders::_1;
class MinimalSubscriber : public rclcpp::Node {
public:
MinimalSubscriber() : Node("minimal_subscriber") {
// Create subscriber and bind callback function
subscription_ = this->create_subscription<std_msgs::msg::String>(
"robot_status", 10, std::bind(&MinimalSubscriber::topic_callback, this, _1));
}
private:
void topic_callback(const std_msgs::msg::String & msg) const {
RCLCPP_INFO(this->get_logger(), "Received message: '%s'", msg.data.c_str());
}
rclcpp::Subscription<std_msgs::msg::String>::SharedPtr subscription_;
};
int main(int argc, char * argv[]) {
rclcpp::init(argc, argv);
rclcpp::spin(std::make_shared<MinimalSubscriber>());
rclcpp::shutdown();
return 0;
}
CMakeLists.txt 빌드 타겟 설정
demo_nodes_cpp/CMakeLists.txt 파일 하단에 실행 파일 빌드 및 디렉터리 타겟을 명시합니다.
cmake_minimum_required(VERSION 3.8)
project(demo_nodes_cpp)
if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
add_compile_options(-Wall -Wextra -Wpedantic)
endif()
find_package(ament_cmake REQUIRED)
find_package(rclcpp REQUIRED)
find_package(std_msgs REQUIRED)
# Executable configuration for Publisher
add_executable(publisher_node src/publisher_node.cpp)
ament_target_dependencies(publisher_node rclcpp std_msgs)
# Executable configuration for Subscriber
add_executable(subscriber_node src/subscriber_node.cpp)
ament_target_dependencies(subscriber_node rclcpp std_msgs)
# Install targets
install(TARGETS
publisher_node
subscriber_node
DESTINATION lib/${PROJECT_NAME})
ament_package()
ROS2 시스템 구축 및 디버깅 기술 팁
자동 환경 설정 추가: Shell 실행 시 자동으로 ROS2 및 워크스페이스 패키지 환경 변수를 로드하도록 ~/.bashrc 하단에 구문을 등록하세요.
echo "source /opt/ros/humble/setup.bash" >> ~/.bashrc echo "source ~/ros2_ws/install/setup.bash" >> ~/.bashrc source ~/.bashrcROS2 CLI 명령어 디버깅: 노드 네트워크 연결 유무를 실시간으로 모니터링하려면 다음 커맨드를 활용하세요.
ros2 node list ros2 topic list ros2 topic echo /robot_status ros2 topic info /robot_statusfastrtps 및 cyclonedds 미들웨어 변경: 네트워크 지연이 발생할 경우 RMW_IMPLEMENTATION 환경변수를 조절하여 DDS 구현체를 변경하세요.
export RMW_IMPLEMENTATION=rmw_cyclonedds_cpp
ROS2 개발 시 흔히 하는 실수 및 예외 해결법
ROS_DOMAIN_ID 네트워크 충돌로 인한 데이터 수신 불가 현상
문제 발생: 동일 네트워크(LAN 또는 Wi-Fi) 환경에서 여러 사용자가 ROS2 노드를 구동할 때 서로의 토픽이 섞이거나 통신 간섭 현상이 발생합니다.
원인: ROS2 DDS 기본 설정은 ROS_DOMAIN_ID=0으로 고정되어 있습니다. 이로 인해 동일한 Domain ID를 사용하는 모든 노드가 동일한 UDP 멀티캐스트 도메인을 공유합니다.
해결책: 고유한 DOMAIN ID(0 ~ 232 사이의 정수)를 개별 단말에 할당하세요.
export ROS_DOMAIN_ID=42
colcon build 실행 시 CMake target not found 에러
- 문제 발생: colcon build 수행 시 다음 예외 문구가 발생하며 빌드가 중단됩니다.
- CMake Error at CMakeLists.txt: Unknown CMake command "ament_target_dependencies"
- 원인: CMakeLists.txt 파일에 find_package(ament_cmake REQUIRED) 선언이 빠져 있거나 package.xml 내에 의존성 패키지가 지정되지 않았기 때문입니다.
- 해결책: package.xml 파일 내에
rclcpp 및std_msgs 태그가 등록되었는지 점검하세요.
임베디드 리눅스 ROS2 Humble 설치 및 노드 통신 구현 결론
Ubuntu 22.04 LTS 시스템 환경에서 ROS2 Humble 설치 과정을 완료하고 DDS 통신 프레임워크 상에서 C++ 기반 퍼블리셔 및 서브스크라이버 노드를 구성했습니다. ROS2의 분산 가상 네트워크 아키텍처와 rclcpp API 구조를 파악하면 고성능 피지컬 AI 및 제어 알고리즘 모듈을 효율적으로 통합할 수 있습니다.
'Edge AI & Cloud > Robotics' 카테고리의 다른 글
| BLDC 모터 정밀 제어를 위한 FOC(Field Oriented Control) 벡터 제어 수학적 해석 및 Clarke Park 변환 가이드 (0) | 2026.08.04 |
|---|---|
| 현대자동차 아틀라스(Atlas) 분석: Hydraulic vs Electric Actuator와 Physical AI 로봇 제어 (0) | 2026.07.29 |