2024년 6월 27일 목요일

ROS2, 가제보 설치 및 패키지 개발 테크트리

이 글은 ROS2 및 가제보 설치 테크트리를 정리한 것이다. 

좀 더 상세한 내용은 참고한 레퍼런스를 확인한다.

ROS2 준비
환경 설정
개발환경은 우분투 22.04이다. 윈도우 버전에서 설치해 보았으나, 너무 과도한 용량과 개인적으로 제일 싫어하는 라이센스 잔뜩 걸린 윈도우 버전 QT 패키지를 피해서 수동 설치해야 하는 문제가 있어, 우분투로 진행한다.  미리 vscode, sublime 도구가 설치되어 있다고 가정한다.

ROS2 버전은 HUBBLE을 사용한다.

설치
ROS2 설치는 터미널 실행 후 다음과 같이 진행한다. 상세한 설명은 여기(ROS2 설치 문서)를 참고한다.
sudo apt update && sudo apt install 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

apt-cache policy | grep universe

sudo apt update && sudo apt install curl gnupg lsb-release
sudo curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key -o /usr/share/keyrings/ros-archive-keyring.gpg

echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] http://packages.ros.org/ros2/ubuntu $(source /etc/os-release && echo $UBUNTU_CODENAME) main" | sudo tee /etc/apt/sources.list.d/ros2.list > /dev/null

sudo apt update
sudo apt upgrade

sudo apt install ros-humble-desktop

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

설치된 폴더는 다음과 같다.
/opt/ros/humble 아래에, 
/bin 실행파일
/cmake 빌드 설정
/include 헤더
/lib 라이브러리
/opt 기타 의존 패키지
/share 패키지 빌드 환경 설정

설치 테스트
설치가 잘 되었는 지 터미널 창 두개를 띄워 각 창의 명령을 다음과 같이 실행한다.
ros2 run demo_nodes_cpp talker
ros2 run demo_nodes_py listener

문제가 없다면, 제대로 설치된 것이다.

개발도구 설치
다음과 같이 설치한다.
sudo apt update && sudo apt install -y build-essential cmake git libbullet-dev python3-colcon-common-extensions python3-flake8 python3-pip python3-pytest-cov python3-rosdep python3-setuptools python3-vcstool wget
python3 -m pip install -U argcomplete flake8-blind-except flake8-builtins flake8-class-newline flake8-comprehensions flake8-deprecated flake8-docstrings flake8-import-order flake8-quotes pytest-repeat pytest-rerunfailures pytest
sudo apt install --no-install-recommends -y libasio-dev libtinyxml2-dev libcunit1-dev

SLAM, NAVIGATION 패키지 설치
다음과 같이 설치한다. 
sudo apt install ros-humble-gazebo-ros-pkgs
sudo apt install ros-humble-gazebo-ros2-control

sudo apt install ros-humble-cartographer
sudo apt install ros-humble-cartographer-ros

sudo apt install ros-humble-navigation2
sudo apt install ros-humble-nav2-bringup

sudo apt-get install ros-humble-moveit

sudo apt-get install pyqt5-dev-tools
python3 -m pip install --upgrade pip
python3 -m pip install -U catkin_pkg cryptography empy ifcfg lark-parser lxml netifaces numpy opencv-python pyparsing pyyaml setuptools rosdistro
python3 -m pip install -U pydot PyQt5

이외, 외부 패키지는 다음과 같이 설치할 수 있다.
sudo apt install ros-humble-teleop-swist-joy

혹은, 
cd ~/projects/ros2/src
git clone https://github.com/ros2/teleop_twist_joy.git
cd ..
colcon build --symlink-install --packages-select teleop_twist_joy

패키지 빌드, 기본 정보 확인 및 테스트
ROS2는 catkin_make 대신 colcon을 빌드 도구로 사용한다. 
ROS2는 복수 개발 폴더를 제공한다. 빌드 후 devel폴더에 넣는 ROS1은 패키지 의존도를 높여 에러 발생 확률을 높였다. ROS2는 devel 폴더는 없애고, 사용자가 명시적으로 colcon build --symlink-install 명령으로 개발된 패키지를 설치하도록 정책이 변경되었다. 

다음과 같이 터미널 명령을 실행한다.
mkdir -p ~/projects/ros2/src/
cd ~/projects/ros2/
colcon build --symlink-install

에러가 없다면, 성공한것이다. 폴더 구조는 다음과 같다.
/build  빌드 설정 파일
/install  빌드된 라이브러리, 실행 파일 
/log  로그
/src  사용자 패키지 폴더

다음과 같이, pkg create 명령으로 패키지를 하나 만든다.
ros2 pkg create my_first_ros_rclpy_pkg --build-type ament_python --dependencies rclpy std_msgs

다음과 같이 소스 내에 setup.py를 다음과 같이 편집한다.
'console_scripts': [
'helloworld_publisher = my_first_ros_rclpy_pkg.helloworld_publisher:main',
'helloworld_subscriber = my_first_ros_rclpy_pkg.helloworld_subscriber:main',
],

my_first_ros_rclpy_pkg 폴더의 my_first_ros_rclpy_pkg/helloworld_publisher.py 를 다음과 같이 편집한다.
import rclpy
from rclpy.node import Node
from rclpy.qos import QoSProfile
from std_msgs.msg import String

class HelloworldPublisher(Node):
    def __init__(self):
        super().__init__('helloworld_publisher')
        qos_profile = QoSProfile(depth=10)
        self.helloworld_publisher = self.create_publisher(String, 'helloworld', qos_profile)
        self.timer = self.create_timer(1, self.publish_helloworld_msg)
        self.count = 0

    def publish_helloworld_msg(self):
        msg = String()
        msg.data = 'Hello World: {0}'.format(self.count)
        self.helloworld_publisher.publish(msg)
        self.get_logger().info('Published message: {0}'.format(msg.data))
        self.count += 1


def main(args=None):
    rclpy.init(args=args)
    node = HelloworldPublisher()
    try:
        rclpy.spin(node)
    except KeyboardInterrupt:
        node.get_logger().info('Keyboard Interrupt (SIGINT)')
    finally:
        node.destroy_node()
        rclpy.shutdown()

if __name__ == '__main__':
    main()

동일하게 helloworld_subscriber.py를 만들고, 다음과 같이 편집한다.
import rclpy
from rclpy.node import Node
from rclpy.qos import QoSProfile
from std_msgs.msg import String

class HelloworldSubscriber(Node):
    def __init__(self):
        super().__init__('Helloworld_subscriber')
        qos_profile = QoSProfile(depth=10)
        self.helloworld_subscriber = self.create_subscription(
            String,
            'helloworld',
            self.subscribe_topic_message,
            qos_profile)

    def subscribe_topic_message(self, msg):
        self.get_logger().info('Received message: {0}'.format(msg.data))


def main(args=None):
    rclpy.init(args=args)
    node = HelloworldSubscriber()
    try:
        rclpy.spin(node)
    except KeyboardInterrupt:
        node.get_logger().info('Keyboard Interrupt (SIGINT)')
    finally:
        node.destroy_node()
        rclpy.shutdown()

if __name__ == '__main__':
    main()

다시 빌드해 본다.
colcon build --symlink-install

이제 각 터미널에서 다음 명령으로 패키지의 각 노드를 실행한다.
. install/local_setup.bash 
ros2 run my_first_ros_rclpy_pkg helloworld_subscriber 
ros2 run my_first_ros_rclpy_pkg helloworld_publisher 

다음과 같이 메시지 토픽을 주고 받으며 잘 동작하는 것을 확인할 수 있다.

이제, 설치된 패키지를 확인해 보자. 
ros2 pkg list

다음과 같이 터틀봇을 각 터미널에서 실행해 본다.
ros2 run turtlesim turtlesim_node
ros2 run turtlesim turtle_teleop_key

다음과 같이 현재 실행중인 노드 정보도 확인할 수 있다.
ros2 node list
ros2 topic list
ros2 service list
ros2 node info /turtlesim
rqt_graph

ROS2 패키지 노드는 서로 토픽, 서비스, 액션, 파라메터를 주고 받거나 공유한다. 패키지 개발 전에 미리 설계해야 하는 것이 좋다.

가제보 설치
가제보(GAZEBO)는 ROS 기반 시뮬레이션 도구로 유용하다. 다음과 같이 설치한다.
sudo apt-get -y install gazebo

ROS2 및 도구 실행
다음과 같이 ROS2와 도구를 실행한다.
ros2 daemon start
ros2 daemon status

gazebo --verbose

다음과 같이 실행되면 성공한 것이다.

이제, 가제보를 이용해, 물리 법칙에 따라, 설계한 모델을 테스트할 수 있다. 

URDF 모델 패키지 개발
URDF는 " Unified Robotics Description Format"을 나타낸다 . 이는 로봇의 형상 및 기타 속성을 지정하는 데 사용되는 파일 형식이다. URDF 모델을 지원하는 패키지 프로그램을 개발해 본다.

다음 명령을 실행해 기본 패키지를 설치한다.
sudo apt install ros-humble-joint-state-publisher
sudo apt install ros-humble-joint-state-publisher-gui
sudo apt install ros-humble-xacro

작업할 프로그램 패키지를 만든다.
ros2 pkg create --build-type ament_cmake urdf_test

생성된 폴더 안에 다음과 같이 추가 폴더를 생성한다.
cd urdf_test/
mkdir launch urdf

다음과 같이 URDF를 코딩한다.
cd urdf
gedit model.urdf
<?xml version="1.0"?>
<robot name="Robot1">
  <link name="base_link">
    <visual>
      <geometry>
        <cylinder length="1" radius="0.4"/>
      </geometry>
    </visual>
  </link>
</robot>

다음과 같이 패키지 파일을 수정 추가한한다.
cd ..
gedit package.xml

  <exec_depend>joint_state_publisher</exec_depend>
  <exec_depend>robot_state_publisher</exec_depend>
  <exec_depend>rviz</exec_depend>

실행파일을 다음과 같이 생성한다.
cd launch
gedit display.launch.py

이 파이썬 파일의 코드는 다음과 같다.
import launch
from launch.substitutions import Command, LaunchConfiguration
import launch_ros
import os

def generate_launch_description():
    pkgPath = launch_ros.substitutions.FindPackageShare(package='urdf_test').find('urdf_test')
    urdfModelPath= os.path.join(pkgPath, 'urdf/model.urdf')
    
    with open(urdfModelPath,'r') as infp:
    robot_desc = infp.read()
    
    params = {'robot_description': robot_desc}
    
    robot_state_publisher_node =launch_ros.actions.Node(
    package='robot_state_publisher',
executable='robot_state_publisher',
    output='screen',
    parameters=[params])
    
    
    joint_state_publisher_node = launch_ros.actions.Node(
        package='joint_state_publisher',
        executable='joint_state_publisher',
        name='joint_state_publisher',
        parameters=[params],
        condition=launch.conditions.UnlessCondition(LaunchConfiguration('gui'))
    )
    joint_state_publisher_gui_node = launch_ros.actions.Node(
        package='joint_state_publisher_gui',
        executable='joint_state_publisher_gui',
        name='joint_state_publisher_gui',
        condition=launch.conditions.IfCondition(LaunchConfiguration('gui'))
    )
    
    rviz_node = launch_ros.actions.Node(
        package='rviz2',
        executable='rviz2',
        name='rviz2',
        output='screen'
    )

    return launch.LaunchDescription([
        launch.actions.DeclareLaunchArgument(name='gui', default_value='True',
                                            description='This is a flag for joint_state_publisher_gui'),
        launch.actions.DeclareLaunchArgument(name='model', default_value=urdfModelPath,
                                            description='Path to the urdf model file'),
        robot_state_publisher_node,
        joint_state_publisher_node,
        joint_state_publisher_gui_node,
        rviz_node
    ]) 

빌드를 위해 cmake 파일을 생성한다.
cd ..
gedit CMakeLists.txt

if(BUILD_TESTING) 문장 위에 다음과 같이 수정한다.
install(
  DIRECTORY launch urdf
  DESTINATION share/${PROJECT_NAME}
)

if(BUILD_TESTING)

빌드한다.
colcon build
source ~/projects/ros2/install/setup.bash

RVIZ를 시작한다.
ros2 launch urdf_test display.launch.py

RVIZ 실행 후 설정은 다음과 같도록 한다. 그럼, 모델링된 URDF를 볼 수 있다.

부록: 가제보와 연결해 시뮬레이션하는 방법
이 내용은 정보가 많지는 않다. 다만, gazebo_ros_pkgs libgazebo_ros_laser 와 같은 패키지가 있으며, 다음과 같이 시뮬레이션 관련 프로젝트가 진행 중에 있어, 여기서 일부 내용을 확인할 수 있다.

레퍼런스

댓글 없음:

댓글 쓰기