로봇을 만드는데 설계를 하고 부품을 구입하고 조립하면서 동작을 여러가지로 시도하면서 할 수 있습니다. 로봇이란 것이 물리적으로 동작을 하기 때문에 예기치 않은 동작에 부품이 고장나거나 망가지면 돈과 시간을 허비하게 됩니다.
ROS2와 연동하여 로봇 시뮬레이션을 할 수 있는 프로그램이 가제보(gazebo) 입니다. ROS2와 가제보에서 시뮬레이션을 위한 작업공간(workspace)를 만드는 방법입니다.
1. 가제보(gazebo) 프로그램 설치
가제보의 Fortress(발표일 : Sep 2021, EOL : Sep 2026) 버전을 설치 합니다. 가제보를 설치하기 위해서는 루트 권한을 갖고 있어야 하고 다음과 같이 먼저 필수 패키지를 설치 합니다.
$ sudo apt update $ sudo apt install lsb-release wget gnupg |
가제보(gazebo)는 우분투 기본 저장소에서 지원을 하지 않고 별도의 저장소를 사용 합니다. 다음과 같이 키와 저장소를 추가 합니다.
$ sudo wget https://packages.osrfoundation.org/gazebo.gpg -O /usr/share/keyrings/pkgs-osrf-archive-keyring.gpg $ echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/pkgs-osrf-archive-keyring.gpg] http://packages.osrfoundation.org/gazebo/ubuntu-stable $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/gazebo-stable.list > /dev/null |
저장소가 등록되면 가제보 프로그램을 설치 할 수 있습니다.
$ sudo apt update $ sudo apt install ignition-fortress |
가제보 프로그램 삭제
가제보 프로그램은 다음과 같이 삭제를 할 수 있습니다.
$ sudo apt remove ignition-fortress && sudo apt autoremove |
2. ROS2 작업공간 만들기
우분투에 ROS2 설치를 하면 설치된 디렉토리는 /opt/ros 입니다. ros 밑에는 ros의 설치된 버전의 코드네임으로 디렉토리가 생성되고 설치 됩니다. ros2-foxy 버전이 설치되었다면 /opt/ros/foxy 디렉토리가 보일 것이고 ros2의 환경설정은 다음과 같습니다.
$ source /opt/ros/foxy/setup.bash |
ROS2로 프로그램을 작성할 때 가장 먼저 작업공간(workspace)를 만들어야 합니다. 적당한 디렉토리를 생성한 후에 디렉토리에서 다음 명령을 실행 합니다.
$ colcon build |
작업공간이라고 해서 거창한 것은 아니고 하위 디렉토리에 build, install, log 디렉토리가 생성 됩니다. install 디렉토리 밑에는 이 작업공간을 ROS2에서 인식할 수 있도록 환경 설정을 위한 쉘파일이 있습니다. /opt/ros/foxy/setup.bash 파일은 ROS2의 전역(global) 환경설정이라면 이 작업공간을 로컬(local) 환경설정은 다음과 같습니다.
$ source ./install/local_setup.bash |
매번 실행하는 것이 귀찮다면 .bashrc 파일에 추가를 해도 됩니다. 다만, 여러 개의 작업공간을 만들어 놓았을 때는 터미널을 열 때마다 실행하는 것이 좋습니다.
3. ROS2 패키지(package) 만들기
ROS2의 패키지 생성은 ros2 유틸리티를 통해서 만들 수 있습니다. 작업공간(workspace)에서 다음과 같이 실행을 합니다.
$ ros2 pkg create --build-type ament_cmake manipulator |
--build-type에는 대표적으로 ament_cmake와 ament_python이 있습니다. 위와 같이 패키지를 생성하면 비어있는 패키지가 하나 생성 됩니다.
4. URDF 시뮬레이션 환경 만들기
URDF(Unified Robot Description Format)는 ROS2에서 로봇을 시뮬레이션을 하기 위한 로봇을 설명한 파일 입니다. 이 문서에서는 URDF를 ROS2에서 시뮬레이션 화면까지 실행하는 것을 목표로 합니다.
위에서 manipulator라는 패키지가 생성되면 작업공간(workspace) 밑에 manipulator 이름으로 디렉토리가 생성 됩니다. 시뮬레이션을 위해서는 manipulator 디렉토리에 추가 디렉토리를 생성해야 합니다.
$ cd manipulator $ mkdir config launch maps meshes models params rviz urdf worlds $ cd .. |
예제 URDF 파일
다음 manipulator.urdf를 manipulator/urdf 디렉토리에 생성을 합니다.
<?xml version="1.0" ?>
<robot name="manipulator" xmlns:xacro="http://ros.org/wiki/xacro">
</robot>
package.xml 파일
ros2에서 패키지를 생성하면 패키지 디렉토리에 package.xml 파일이 생성됩니다. 패키지에 대한 속성 및 설명을 하며 시뮬레이션에 필요한 속성을 <buildtool_depend>ament_cmake</buildtool_depend> 라인 밑에 다음과 같이 추가를 합니다.
<exec_depend>joint_state_publisher</exec_depend>
<exec_depend>robot_state_publisher</exec_depend>
<exec_depend>rviz</exec_depend>
<exec_depend>xacro</exec_depend>
위에서 "joint_state_publisher" 패키지를 추가로 설치를 해 주어야 합니다. 패키지는 ROS2 버전에 맞는 버전을 다음과 같이 추가로 설치를 합니다.
$ sudo apt install ros-foxy-joint-state-publisher-gui |
버전이 설치되어 있는지는 다음 명령을 통해서 확인을 할 수 있습니다.
$ dpkg -L ros-foxy-joint-state-publisher-gui |
런처(launch) 파일
이 예제에서는 사용하지 않지만 URDF를 작성하는데 xacro 패키지는 유용 합니다. 런처에서 xacro를 사용하도록 작성이 되었기 때문에 xacro 패키지를 설치해야 합니다.
$ sudo apt install ros-foxy-xacro |
다음 런처파일을 manipulator/launch/manipulator.launch.py로 저장을 합니다.
import os
from launch import LaunchDescription
from launch.actions import DeclareLaunchArgument
from launch.conditions import IfCondition, UnlessCondition
from launch.substitutions import Command, LaunchConfiguration
from launch_ros.actions import Node
from launch_ros.substitutions import FindPackageShare
def generate_launch_description():
# Set the path to this package.
pkg_share = FindPackageShare(package='manipulator').find('manipulator')
# Set the path to the RViz configuration settings
default_rviz_config_path = os.path.join(pkg_share, 'rviz/rviz_basic_settings.rviz')
# Set the path to the URDF file
default_urdf_model_path = os.path.join(pkg_share, 'urdf/manipulator.urdf')
########### YOU DO NOT NEED TO CHANGE ANYTHING BELOW THIS LINE ##############
# Launch configuration variables specific to simulation
gui = LaunchConfiguration('gui')
urdf_model = LaunchConfiguration('urdf_model')
rviz_config_file = LaunchConfiguration('rviz_config_file')
use_robot_state_pub = LaunchConfiguration('use_robot_state_pub')
use_rviz = LaunchConfiguration('use_rviz')
use_sim_time = LaunchConfiguration('use_sim_time')
# Declare the launch arguments
declare_urdf_model_path_cmd = DeclareLaunchArgument(
name='urdf_model',
default_value=default_urdf_model_path,
description='Absolute path to robot urdf file')
declare_rviz_config_file_cmd = DeclareLaunchArgument(
name='rviz_config_file',
default_value=default_rviz_config_path,
description='Full path to the RVIZ config file to use')
declare_use_joint_state_publisher_cmd = DeclareLaunchArgument(
name='gui',
default_value='True',
description='Flag to enable joint_state_publisher_gui')
declare_use_robot_state_pub_cmd = DeclareLaunchArgument(
name='use_robot_state_pub',
default_value='True',
description='Whether to start the robot state publisher')
declare_use_rviz_cmd = DeclareLaunchArgument(
name='use_rviz',
default_value='True',
description='Whether to start RVIZ')
declare_use_sim_time_cmd = DeclareLaunchArgument(
name='use_sim_time',
default_value='True',
description='Use simulation (Gazebo) clock if true')
# Specify the actions
# Publish the joint state values for the non-fixed joints in the URDF file.
start_joint_state_publisher_cmd = Node(
condition=UnlessCondition(gui),
package='joint_state_publisher',
executable='joint_state_publisher',
name='joint_state_publisher')
# A GUI to manipulate the joint state values
start_joint_state_publisher_gui_node = Node(
condition=IfCondition(gui),
package='joint_state_publisher_gui',
executable='joint_state_publisher_gui',
name='joint_state_publisher_gui')
# Subscribe to the joint states of the robot, and publish the 3D pose of each link.
start_robot_state_publisher_cmd = Node(
condition=IfCondition(use_robot_state_pub),
package='robot_state_publisher',
executable='robot_state_publisher',
parameters=[{'use_sim_time': use_sim_time,
'robot_description': Command(['xacro ', urdf_model])}],
arguments=[default_urdf_model_path])
# Launch RViz
start_rviz_cmd = Node(
condition=IfCondition(use_rviz),
package='rviz2',
executable='rviz2',
name='rviz2',
output='screen',
arguments=['-d', rviz_config_file])
# Create the launch description and populate
ld = LaunchDescription()
# Declare the launch options
ld.add_action(declare_urdf_model_path_cmd)
ld.add_action(declare_rviz_config_file_cmd)
ld.add_action(declare_use_joint_state_publisher_cmd)
ld.add_action(declare_use_robot_state_pub_cmd)
ld.add_action(declare_use_rviz_cmd)
ld.add_action(declare_use_sim_time_cmd)
# Add any actions
ld.add_action(start_joint_state_publisher_cmd)
ld.add_action(start_joint_state_publisher_gui_node)
ld.add_action(start_robot_state_publisher_cmd)
ld.add_action(start_rviz_cmd)
return ld
rviz 설정 파일
다음 rviz 설정 파일을 manipulator/rviz/rviz_basic_settings.rviz로 저장을 합니다. (런처 파일에 정의되어 있습니다.)
Panels:
- Class: rviz_common/Displays
Help Height: 78
Name: Displays
Property Tree Widget:
Expanded:
- /Global Options1
- /Status1
- /RobotModel1
- /TF1
- /TF1/Frames1
Splitter Ratio: 0.5
Tree Height: 617
- Class: rviz_common/Selection
Name: Selection
- Class: rviz_common/Tool Properties
Expanded:
- /2D Goal Pose1
- /Publish Point1
Name: Tool Properties
Splitter Ratio: 0.5886790156364441
- Class: rviz_common/Views
Expanded:
- /Current View1
Name: Views
Splitter Ratio: 0.5
Visualization Manager:
Class: ""
Displays:
- Alpha: 0.5
Cell Size: 1
Class: rviz_default_plugins/Grid
Color: 160; 160; 164
Enabled: true
Line Style:
Line Width: 0.029999999329447746
Value: Lines
Name: Grid
Normal Cell Count: 0
Offset:
X: 0
Y: 0
Z: 0
Plane: XY
Plane Cell Count: 10
Reference Frame: <Fixed Frame>
Value: true
- Alpha: 1
Class: rviz_default_plugins/RobotModel
Collision Enabled: false
Description File: ""
Description Source: Topic
Description Topic:
Depth: 5
Durability Policy: Volatile
History Policy: Keep Last
Reliability Policy: Reliable
Value: /robot_description
Enabled: true
Links:
All Links Enabled: true
Expand Joint Details: false
Expand Link Details: false
Expand Tree: false
Link Tree Style: Links in Alphabetic Order
base_footprint:
Alpha: 1
Show Axes: false
Show Trail: false
base_link:
Alpha: 1
Show Axes: false
Show Trail: false
Value: true
drivewhl_l_link:
Alpha: 1
Show Axes: false
Show Trail: false
Value: true
drivewhl_r_link:
Alpha: 1
Show Axes: false
Show Trail: false
Value: true
front_caster:
Alpha: 1
Show Axes: false
Show Trail: false
Value: true
gps_link:
Alpha: 1
Show Axes: false
Show Trail: false
imu_link:
Alpha: 1
Show Axes: false
Show Trail: false
lidar_link:
Alpha: 1
Show Axes: false
Show Trail: false
Value: true
Name: RobotModel
TF Prefix: ""
Update Interval: 0
Value: true
Visual Enabled: true
- Class: rviz_default_plugins/TF
Enabled: true
Frame Timeout: 15
Frames:
All Enabled: false
base_footprint:
Value: false
base_link:
Value: false
drivewhl_l_link:
Value: true
drivewhl_r_link:
Value: true
front_caster:
Value: false
gps_link:
Value: false
imu_link:
Value: false
lidar_link:
Value: false
Marker Scale: 1
Name: TF
Show Arrows: false
Show Axes: true
Show Names: true
Tree:
base_footprint:
base_link:
drivewhl_l_link:
{}
drivewhl_r_link:
{}
front_caster:
{}
gps_link:
{}
imu_link:
{}
lidar_link:
{}
Update Interval: 0
Value: true
Enabled: true
Global Options:
Background Color: 48; 48; 48
Fixed Frame: base_link
Frame Rate: 30
Name: root
Tools:
- Class: rviz_default_plugins/Interact
Hide Inactive Objects: true
- Class: rviz_default_plugins/MoveCamera
- Class: rviz_default_plugins/Select
- Class: rviz_default_plugins/FocusCamera
- Class: rviz_default_plugins/Measure
Line color: 128; 128; 0
- Class: rviz_default_plugins/SetInitialPose
Topic:
Depth: 5
Durability Policy: Volatile
History Policy: Keep Last
Reliability Policy: Reliable
Value: /initialpose
- Class: rviz_default_plugins/SetGoal
Topic:
Depth: 5
Durability Policy: Volatile
History Policy: Keep Last
Reliability Policy: Reliable
Value: /goal_pose
- Class: rviz_default_plugins/PublishPoint
Single click: true
Topic:
Depth: 5
Durability Policy: Volatile
History Policy: Keep Last
Reliability Policy: Reliable
Value: /clicked_point
Transformation:
Current:
Class: rviz_default_plugins/TF
Value: true
Views:
Current:
Class: rviz_default_plugins/Orbit
Distance: 4.434264183044434
Enable Stereo Rendering:
Stereo Eye Separation: 0.05999999865889549
Stereo Focal Distance: 1
Swap Stereo Eyes: false
Value: false
Focal Point:
X: 0.31193429231643677
Y: 0.11948385089635849
Z: -0.4807402193546295
Focal Shape Fixed Size: true
Focal Shape Size: 0.05000000074505806
Invert Z Axis: false
Name: Current View
Near Clip Distance: 0.009999999776482582
Pitch: 0.490397572517395
Target Frame: <Fixed Frame>
Value: Orbit (rviz)
Yaw: 1.0503965616226196
Saved: ~
Window Geometry:
Displays:
collapsed: false
Height: 846
Hide Left Dock: false
Hide Right Dock: false
QMainWindow State: 000000ff00000000fd000000040000000000000156000002f4fc0200000008fb0000001200530065006c0065006300740069006f006e00000001e10000009b0000005c00fffffffb0000001e0054006f006f006c002000500072006f007000650072007400690065007302000001ed000001df00000185000000a3fb000000120056006900650077007300200054006f006f02000001df000002110000018500000122fb000000200054006f006f006c002000500072006f0070006500720074006900650073003203000002880000011d000002210000017afb000000100044006900730070006c006100790073010000003d000002f4000000c900fffffffb0000002000730065006c0065006300740069006f006e00200062007500660066006500720200000138000000aa0000023a00000294fb00000014005700690064006500530074006500720065006f02000000e6000000d2000003ee0000030bfb0000000c004b0069006e0065006300740200000186000001060000030c00000261000000010000010f000002f4fc0200000003fb0000001e0054006f006f006c002000500072006f00700065007200740069006500730100000041000000780000000000000000fb0000000a00560069006500770073010000003d000002f4000000a400fffffffb0000001200530065006c0065006300740069006f006e010000025a000000b200000000000000000000000200000490000000a9fc0100000001fb0000000a00560069006500770073030000004e00000080000002e10000019700000003000004420000003efc0100000002fb0000000800540069006d00650100000000000004420000000000000000fb0000000800540069006d006501000000000000045000000000000000000000023f000002f400000004000000040000000800000008fc0000000100000002000000010000000a0054006f006f006c00730100000000ffffffff0000000000000000
Selection:
collapsed: false
Tool Properties:
collapsed: false
Views:
collapsed: false
Width: 1200
X: 246
Y: 77
CMakeLists.txt 파일
amend_cmake는 CMakeLists.txt파일을 참조하여 패키지를 빌드 합니다. 새롭게 추가된 디렉토리를 추가해야 패키지 빌드시에 적용됩니다. 다음과 같이 CMakeLists.txt파일에 추가를 합니다.
install(
DIRECTORY config launch maps meshes models params rviz src urdf worlds
DESTINATION share/${PROJECT_NAME}
)
5. ROS2 패키지 빌드
ROS2의 빌드 시스템은 colcon입니다. colcon으로 빌드를 합니다.
$ colcon build or $ colcon build --packages-select manipulator |
6. 시뮬레이션 실행
패키지 빌드가 성공을 하였다면 다음과 같이 실행을 하면 로봇이 없는 시뮬레이션 화면이 실행 됩니다.
$ ros2 launch manipulator manipulator.launch.py |
manipulator/urdf/manipulator.urdf에 로봇을 추가하면 화면에 추가한 로봇이 보이게 됩니다.
7. 예제
'로봇 이야기 > ros2' 카테고리의 다른 글
기구학 (Kinematics) 이란? (0) | 2023.01.03 |
---|---|
매니퓰레이터(manipulator) URDF 모델링 (0) | 2022.12.31 |
xacro (XML macro) (0) | 2022.12.30 |
URDF(Unified Robot Description Format)란? (0) | 2022.12.13 |
ROS2 설치 - foxy (0) | 2022.12.13 |
댓글