์ด๋ฒ์๋ Ch7. ํจํค์ง ๋ง๋ค๊ณ ํ ํฝ ๋ค๋ฃจ๊ธฐ์ ๋ํด์ ์ฐ๊ณ ์ ํ๋ค.
์ด๋ฒ ์ฅ์์๋ ํจํค์ง๋ฅผ ์๋กญ๊ฒ ๋ง๋ค๊ณ , ์์ ๋ฐฐ์ด ๋ช ๋ น์ ์ด์ฉํด ํ ํฝ, ์๋น์ค ๋ฑ์ ํจํค์ง ๋ด์์ ๋ง๋ค์ด ๋ณผ ๊ฒ์ด๋ค.
1. ์ค์น ๋ฐ ์ค๋น
์์์ ์ค์นํ์์ง๋ง, ์ค์นํ์ง ์์ ์ฌ๋๋ค์ ์ํด์ ์์ฑํ๋ ๋ถ๋ถ์ด๋ค.
์์ ๊ธ ์ค์ ์ด ๊ธ์์ Humble ์ค์น ์ค์ Install development tools and ROS tools๋ผ๋ ๋ถ๋ถ์ ์ค์น๋ฅผ ํ์ง ์์๋ค๋ฉด ๊ทธ ๋ถ๋ถ์ ์ค์นํด์ผ ํ๋ค.
๋ฌด์์ ๊ณต๋ถํ๊ธฐ - ํผ์ ๊ณต๋ถํ๋ ๋ก๋ด SW ๋ฐ๋ผํ๊ธฐ (1)
1ํ๋ ๋๋ถํฐ ๊ฐ์ง๊ณ ์๋ ์์์ธ ROS ๊ณต๋ถ๋ฅผ ์ด๋ฒ์ ubuntu 22.04๊ฐ ์ฐ๋ถํฌ๊ฐ ๊น๋ฆฌ์ง ์๋ ๋ ธํธ๋ถ์ ๊น๋ฆฌ๋ฉด์ ์์ํ ์ ์๊ฒ ๋์๋ค.(๊ฐ์ฌํฉ๋๋ค...) ๊ทธ๋์ ๊ฐ์ง๊ณ ์๋ ์ฑ ์ค ROS2๋ฅผ ๊ณต๋ถํ๊ณ ์ ํ
mosw.tistory.com
๊ทธ๋ ์ ์ํ๋ ๊ณต์ ํํ์ด์ง์์ ๋ช ๋ น์ด๋ฅผ ๋ณต์ฌํด์ ์ค์น๋ฅผ ์งํํด์ค๋ค.
๋งํฌ๋ ๋ค์๊ณผ ๊ฐ๋ค.
Ubuntu (source) — ROS 2 Documentation: Humble documentation
If you have already installed ROS 2 another way (either via Debians or the binary distribution), make sure that you run the below commands in a fresh environment that does not have those other installations sourced. Also ensure that you do not have source
docs.ros.org
sudo apt update && sudo apt install -y \
python3-flake8-docstrings \
python3-pip \
python3-pytest-cov \
ros-dev-tools
sudo apt install -y \
python3-flake8-blind-except \
python3-flake8-builtins \
python3-flake8-class-newline \
python3-flake8-comprehensions \
python3-flake8-deprecated \
python3-flake8-import-order \
python3-flake8-quotes \
python3-pytest-repeat \
python3-pytest-rerunfailures
์ด ์ฝ๋๋ ํ์ฌ ์ํฉ์์์ ์ฝ๋์ด๋ฏ๋ก, ์ค์ค๋ก ์ ์ํด์ ์ค์นํ๊ธฐ๋ฅผ ์ถ์ฒํ๋ค.
(+humble์ ํจ ๋ค์ ์ค์นํด์ผ ์ ์์ ์ผ๋ก ์ค์น๋๋ค.)
์ดํ mkdir ๋ช ๋ น์ ์ด์ฉํด์ ~/ros2_study/src ํด๋๋ฅผ ๋ง๋ค๊ณ ๊ทธ ํด๋์ ๋ค์ด๊ฐ๋ค.
์ดํ ์ด ํด๋์์ colcon build๋ผ๋ ๋ช ๋ น์ ์คํํ๋ค.
์ด ๋ช ๋ น์ด๋ค์ ros2_study ํด๋์ ๊ทธ ์์ src๋ผ๋ ์์ค์ฝ๋ ํด๋๋ฅผ ๋ง๋ค๊ณ , ๊ทธ ์์์ src, ์ฆ ์์ค ์ฝ๋๋ค์ ๋น๋ํ๋ผ๋ ๋ช ๋ น์ด์ด๋ค.
colcon build
ํ์ง๋ง, ์ง๊ธ์ ์๋ฌด ์ฝ๋๋ ์๊ธฐ์ build ๋์ง ์๋๋ค.
ํ์ง๋ง build์ install, log ํด๋๊ฐ ์๋ก ์๊ธฐ๋ ๊ฒ์ ๋ณผ ์ ์๋ค.
2. ํจํค์ง ๋ง๋ค๊ธฐ
์ํฌ์คํ์ด์ค(ros2_study)๋ก ์ด๋ํ์ฌ src ํด๋๋ก ์ด๋ํ์ฌ ๋ค์์ ์ฝ๋๋ฅผ ์์ฑํ์ฌ ํจํค์ง๋ฅผ ๋ง๋ค ์ ์๋ค.
ros2 pkg create --build-type ament_python --node-name my_first_node my_first_package
์ด ์ฝ๋๋ฅผ ์ด์ฉํ๋ฉด my_first_package ํจํค์ง๋ฅผ ๋ง๋ค๊ณ , my_first_node ์ด๋ฆ์ ๋ ธ๋๋ฅผ ๋ง๋ค ์ ์๋ค.
์ดํ ํด๋ ์ฒดํฌ์ ํธํ tree๋ฅผ ๋ค์ ๋ช ๋ น์ด๋ก ์ค์นํด ์ค ๋ค tree ๋ช ๋ น์ด๋ก ํ์ธํด ์ฃผ๋ฉด ๋ค์๊ณผ ๊ฐ์ด ๊ตฌ์กฐ๊ฐ ์๊ธด ๊ฒ์ ํ์ธ ๊ฐ๋ฅํ๋ค.
sudo apt install tree
์ด ํด๋์์ ์ฃผ๋ก ์ฐ๋ ํธ์ง๊ธฐ๋ก ์ด๋ฉด, ์ด๋ฅผ ํธ์ง๊ธฐ๋ก ์์ ์ด ๊ฐ๋ฅํด์ง๋ค.
์ฌ๊ธฐ์ my_first_node๋ง ๋ณด์.
์ด๋ฅผ ๋ณด๋ฉด ๋จ์ํ๊ฒ main ํจ์์ ๋ด์ฉ์ ํ๋ฆฐํธํ๋ ์ฝ๋ฉ์ด๋ค.
์ด์ ์์์ ์งํํ ๊ฒ์ฒ๋ผ colcon ๋น๋ ํด์ ์ด์ฉํด์ ๋น๋ํด๋ณด๊ณ ์ ํ๋ค.
3. ํจํค์ง ๋น๋ํ๊ณ ์ํฌ ์คํ์ด์ค ์ค์ ํ๊ธฐ
ํ์ฌ ์ํ์์ colocn build๋ฅผ ์ด์ฉํด ๋ณด์.
๋ค์์ ๋ฌธ๊ตฌ์ ํจ๊ป ์ฑ๊ณตํ๋ค๊ณ ๋ฐ ๊ฒ์ด๋ค.
์ด์ ์์์ ๋ง๋ node๋ฅผ ์คํํด ๋ณด์.
ros2 run my_first_package my_first_node
๊ทธ๋ฅ ์คํํ๋ฉด ์ด๋ ๊ฒ ๋น๋ํ๋๋ฐ๋ ์คํ๋์ง ์๋ ์ค๋ฅ๋ฅผ ๊ฒช์ ๊ฒ์ด๋ค.
์ด์ ๋ ๋น๋ํ ํ๊ฒฝ์ ์ฝ์ง ๋ชปํด์์ด๋ค.
๋ฐ๋ผ์ ์ํฌ ์คํ์ด์ค์ install ์์ local_setup.bash๋ฅผ ๋ถ๋ฌ์จ ๋ค ๋ค์ ์คํํด๋ณด๊ณ ์ ํ๋ค.
์ด์ ์ด๋ฅผ ์ ์ ํ๋ alias๋ฅผ ์ด์ฉํด์ ํธํ๊ฒ ํ ์ ์๋๋ก ํ๋ ค๊ณ ํ๋ค.
~/.bashrc์ ๋ง์ง๋ง์ ๋ค์๊ณผ ๊ฐ์ ๋ฌธ๊ตฌ๋ฅผ ์ถ๊ฐํด ๋ณด์.
alias ros2study="humble; source ~/ros2_study/install/local_setup.bash; echo \"ros2_study workspace is activated.\""
์ดํ sb ๋ช ๋ น์ด๋ฅผ ์ด์ฉํด ์ ์ฉํด ์ฃผ์.
๊ทธ๋ฌ๋ฉด ์ด๋ ๊ฒ ์ ์๋ํ๋ ๋ชจ์ต์ ๋ณผ ์ ์๋ค.
์ด์ Topic Subscriber๋ผ๋ ๋ ธ๋๋ฅผ ์ถ๊ฐํด ๋ณด๋๋ก ํ๊ฒ ๋ค.
4. Topic Subscriber ๋ ธ๋ ์ถ๊ฐ
๊ฐ์ฅ ๋จผ์ , my_first_package ํด๋์ my_subscriber๋ผ๋ ํ์ผ์ ๋ง๋ค์๋ค.
์ดํ ๋ค์๊ณผ ๊ฐ์ ์ฝ๋๋ฅผ ์์ฑํ๋ค.
import rclpy as rp
from rclpy.node import Node
from turtlesim.msg import Pose
class TurtlesimSubscriber(Node):
def __init__(self):
super().__init__('turtlesim_subscriber')
self.subscription = self.create_subscription(
Pose,
'/turtle1/pose',
self.callback,
10)
self.subscription #prevent unsued variable warning
def callback(self,msg):
print("X : ", msg.x, ", Y : ", msg.y)
def main(args=None):
rp.init(args=args)
turtlesim_subscriber = TurtlesimSubscriber()
rp.spin(turtlesim_subscriber)
turtlesim_subscriber.destroy_node()
rp.shutdown()
if __name__ == '__main__':
main()
์ดํ ์ด๋ฅผ ์คํํ๊ธฐ ์ํด์ ์ ๊น setup.py๋ฅผ ์์ ํ๋ค๋ฉด ๋ค์๊ณผ ๊ฐ์ ๋ชจ์ต์ผ ํ ๋ฐ, entry_point์ ๋ค์๊ณผ ๊ฐ์ ๋ฌธ์ฅ์ ์ถ๊ฐํ๋ค.
'my_subscriber = my_first_package.my_subscriber:main'
์ดํ ๋ค์ ros2_study๋ก ๋์๊ฐ์ build ํ๋ฉด ์ด์ ๋ช ๋ น ์ํ์ด ๊ฐ๋ฅํด์ง๋ค.
๊ทธ๋ฆฌ๊ณ ํ์ชฝ ํฐ๋ฏธ๋์์ turtlesim_node๋ฅผ, ๊ทธ๋ฆฌ๊ณ ํ์ชฝ์์๋ ๋ฐฉ๊ธ ๋ง๋ ๋ ธ๋๋ฅผ ์คํํ๋ค๋ฉด x, y ๊ฐ์ ์ฝ์ด์ค๋ ๊ฒ์ ์ ์ ์๋ค.
์ด๋ฅผ rqt_graph๋ก ํ์ธํ๋ฉด ๋ค์๊ณผ ๊ฐ์ ํ๋ฆ์ธ ๊ฒ์ ํ์ธ ๊ฐ๋ฅํ๋ค.
5. Topic Publisher ๋ ธ๋ ์ถ๊ฐ
์ด์ ๋ cmd_vel ํ ํฝ์ ๋ฐํํ๊ธฐ ์ํด์ ์์์ ํ ๊ฒ์ฒ๋ผ my_publisher.py ํ์ผ์ ๋ง๋ค๊ณ ์ด์ ๋ํด์ ๋ค์๊ณผ ๊ฐ์ด ์์ฑํ๋๋ก ํ์๋ค.
import rclpy as rp
from rclpy.node import Node
from geometry_msgs.msg import Twist
class TurtlesimPublisher(Node):
def __init__(self):
super().__init__('turtlesim_publisher')
self.publisher = self.create_publisher(Twist, '/turtle1/cmd_vel', 10)
timer_period = 0.5
self.timer = self.create_timer(timer_period, self.timer_callback)
def timer_callback(self):
msg = Twist()
msg.linear.x = 2.0
msg.angular.z = 2.0
self.publisher.publish(msg)
def main(args=None):
rp.init(args=args)
turtlesim_publisher = TurtlesimPublisher()
rp.spin(turtlesim_publisher)
turtlesim_publisher.destroy_node()
rp.shutdown()
if __name__ == '__main__':
main()
์ดํ ์๊ณผ ๋ง์ฐฌ๊ฐ์ง๋ก setup.py์ my_publisher ๋ ธ๋๋ฅผ ์ถ๊ฐํ๋ค.
'my_publisher = my_first_package.my_publisher:main'
๋ํ ์์์ ๋น๋ํ ์ ๋ณด๋ฅผ ์ง์์ผ ํ ํ์๊ฐ ์์ ์ ์์ผ๋, ์ง์ฐ๋ ๋ฐฉ๋ฒ์ ์๋ ค์ฃผ์๋ฉด
์ํฌ ์คํ์ด์ค์ ํ๊ฒฝ์์ ๋ค์์ ๋ช ๋ น์ด๋ฅผ ์ด์ฉํด build, install, log ์ ๋ณด๋ฅผ ์ง์ธ ์ ์๋ค.
์ดํ ๋ค์ colcon build ๋ช ๋ น์ด๋ฅผ ์ด์ฉํด ๋ค์ ๋น๋ํ ์ ์๋ค.
sudo rm -r build install log
์ดํ turtlesim, my_publisher, my_subscriber๋ฅผ ์คํํ๋ฉด ๋ค์๊ณผ ๊ฐ์ ๋ชจ์ต์ ๋ณผ ์ ์๋ค.
์ดํ rqt_graph๋ฅผ ์คํํ๋ฉด ๋ค์๊ณผ ๊ฐ์ด ์คํ๋๋ ๊ฒ์ ๋ณผ ์ ์๋ค.
6. ๋ง๋ฌด๋ฆฌ
๋ค์ ๊ธ์์๋ 'Ch8. ๋ฉ์์ง ์ ์ ๋ง๋ค๊ณ ํ ํฝ๊ณผ ์๋น์ค์์ ๋ค๋ฃจ๊ธฐ'์ ๋ํด์ ์ฐ๊ณ ์ ํ๋ค.
์ด๋ฒ์ ์ฐ์ธ ํ์ผ๋ค์ ๋ค์๊ณผ ๊ฐ๋ค.