3 분 소요

Hits

ROS2 Turtle Study

참고 Youtube : ROS2 Tutorial - ROS2 Humble

vim ~/.bashrc

위와 같이 들어가서

source /opt/ros/humble/setup.bash
source /usr/share/colcon_argcomplete/hook/colcon-argcomplete.bash
source ~/ros2_ws/install/setup.bash

위와 같이 작성한다

source ~/.bashrc

위와 같이 반영한다

59.6.0 버전이었는데 58.2.0 버전으로 다운그레이드 한다
참고

sudo apt install python3-pip
pip3 list | grep setuptools
pip install setuptools==58.2.0

Turtlesim Install

Turtlesim Tutorials

Start

ros2 run turtlesim turtlesim_node

Use

ros2 run turtlesim turtle_teleop_key

각 명령의 하위 명령을 사용하면 노드와 관련 주제, 서비스, 작업을 볼 수 있습니다.

ros2 node list
ros2 topic list
ros2 service list
ros2 action list

기타

ros2 topic list
ros2 topic info /turtle1/cmd_vel
ros2 interface show geometry_msgs/msg/Twist

위와 같이 interface show 시 아래와 같이 나온다

Vector3  linear
	float64 x
	float64 y
	float64 z
Vector3  angular
	float64 x
	float64 y
	float64 z

이번엔 이렇게 해보자

ros2 service type /turtle1/set_pen
ros2 interface show turtlesim/srv/SetPen 

위와 같이 interface show 시 아래와 같이 나온다

uint8 r
uint8 g
uint8 b
uint8 width
uint8 off

Code Start

mkdir ~/ros2_ws/src
cd ~/ros2_ws/src
ros2 pkg create my_robot_controller --build-type ament_python --dependencies rclpy
cd ~/ros2_ws/src/my_robot_controller/my_robot_controller
touch my_first_node.py
chmod +x my_first_node.py

my_first_node.py

#!/usr/bin/env python3
import rclpy
from rclpy.node import Node

class MyNode(Node):

    def __init__(self):
        super().__init__("first_node")
        self.counter_ = 0
        self.create_timer(1.0, self.timer_callback)
    
    def timer_callback(self):
        self.get_logger().info("Hello from ROS2~~~" + str(self.counter_))
        self.counter_ += 1
    

def main(args=None):
    rclpy.init(args=args) # start
    node = MyNode()
    rclpy.spin(node)
    rclpy.shutdown() # end

if __name__ == "__main__":
    main()

visual studio code 에 확장:마켓플레이스 에서 ROS 설치하면 좋다(Microsoft꺼)

setup.py에서 entry_points={‘console_scripts’: [],}, 안에 아래와 같이 넣고

entry_points={
        'console_scripts': [
            "test_node = my_robot_controller.my_first_node:main"
        ],
    },
cd ~/ros2_ws

로 가서

colcon build
source ~/.bashrc

를 하고

ros2 run my_robot_controller 하고 탭을 치면 test_node 가 나와서

ros2 run my_robot_controller test_node

위와 같이 치면 위에서 my_first_node.py 파일의 main이 실행된다

근데 매번 파일 고치면 colcon build를 해줘야 하는 번거러움이 있다. 그래서

colcon build --symlink-install
source ~/.bashrc

를 해준다

cd ~/ros2_ws/src/my_robot_controller/my_robot_controller
touch draw_circle.py
chmod +x draw_circle.py

draw_circle.py

#!/usr/bin/env python3
import rclpy
from rclpy.node import Node
from geometry_msgs.msg import Twist

class DrawCircleNode(Node):

    def __init__(self):
        super().__init__("draw_circle")
        self.cmd_vel_pub_ = self.create_publisher(Twist, "/turtle1/cmd_vel", 10)
        self.timer_ = self.create_timer(0.5, self.send_velocity_command)
        self.get_logger().info("Draw Start~~~")
    
    def send_velocity_command(self):
        msg = Twist()
        msg.linear.x = 2.0
        msg.angular.z = 1.0
        self.cmd_vel_pub_.publish(msg)

def main(args=None):
    rclpy.init(args=args) # start
    node = DrawCircleNode()
    rclpy.spin(node)
    rclpy.shutdown() # end

package.xml에 rclpy 밑에

<depend>rclpy</depend>
<depend>geometry_msgs</depend>
<depend>turtlesim</depend>

setup.py에서 entry_points={‘console_scripts’: [],}, 안에 아래와 같이 넣고

entry_points={
        'console_scripts': [
            "test_node = my_robot_controller.my_first_node:main",
            "draw_circle = my_robot_controller.draw_circle:main"
        ],
    },
cd ~/ros2_ws/src/my_robot_controller/my_robot_controller
touch pose_subscriber.py
chmod +x pose_subscriber.py

pose_subscriber.py

#!/usr/bin/env python3
import rclpy
from rclpy.node import Node
from turtlesim.msg import Pose

class PoseSubscriberNode(Node):

    def __init__(self):
        super().__init__("pose_subscriber")
        self.pose_subscriber_ = self.create_subscription(
            Pose, "/turtle1/pose", self.pose_callback, 10
        )
    def pose_callback(self, msg: Pose):
        self.get_logger().info("(" + str(msg.x) + ", " + str(msg.y) + ")")

def main(args=None):
    rclpy.init(args=args) # start
    node = PoseSubscriberNode()
    rclpy.spin(node)
    rclpy.shutdown() # end

setup.py에서 entry_points={‘console_scripts’: [],}, 안에 아래와 같이 넣고

entry_points={
        'console_scripts': [
            "test_node = my_robot_controller.my_first_node:main",
            "draw_circle = my_robot_controller.draw_circle:main",
            "pose_subscriber = my_robot_controller.pose_subscriber:main"
        ],
    },
cd ~/ros2_ws/src/my_robot_controller/my_robot_controller
touch turtle_controller.py
chmod +x turtle_controller.py

turtle_controller.py

#!/usr/bin/env python3
import rclpy
from rclpy.node import Node
from turtlesim.msg import Pose
from geometry_msgs.msg import Twist
from turtlesim.srv import SetPen
from functools import partial

class TurtleControllerNode(Node):

    def __init__(self):
        super().__init__("turtle_controller")
        self.previous_x_ = 0
        self.cmd_vel_publisher_ = self.create_publisher(
            Twist, "/turtle1/cmd_vel", 10
        )
        self.pose_subscriber_ = self.create_subscription(
            Pose, "/turtle1/pose", self.pose_callback, 10
        )
        
        self.get_logger().info("Turtle Start~~")

    def pose_callback(self, pose: Pose):
        cmd = Twist()
        if pose.x > 9.0 or pose.x < 2.0 or pose.y > 9.0 or pose.y < 2.0:
            cmd.linear.x = 1.0
            cmd.angular.z = 0.9
        else:
            cmd.linear.x = 5.0
            cmd.angular.z = 0.0
        self.cmd_vel_publisher_.publish(cmd)

        if pose.x > 5.5 and self.previous_x_ <= 5.5:
            self.previous_x_ = pose.x
            self.get_logger().info("Set Color to Red~~")
            self.call_set_pen_service(255, 0, 0, 3, 0)
        elif pose.x <= 5.5 and self.previous_x_ > 5.5:
            self.previous_x_ = pose.x
            self.get_logger().info("Set Color to Green~~")
            self.call_set_pen_service(0, 255, 0, 3, 0)

    def call_set_pen_service(self, r, g, b, width, off):
        client = self.create_client(SetPen, "/turtle1/set_pen")
        while not client.wait_for_service(1.0):
            self.get_logger().warn("Wating for service~~~")

        request = SetPen.Request()
        request.r = r
        request.g = g
        request.b = b
        request.width = width
        request.off = off

        future = client.call_async(request)
        future.add_done_callback(partial(self.callback_set_pen))
    
    def callback_set_pen(self, future):
        try:
            response = future.result()
        except Exception as e:
            self.get_logger().error("Service call failed: %r" % (e, ))

def main(args=None):
    rclpy.init(args=args) # start
    node = TurtleControllerNode()
    rclpy.spin(node)
    rclpy.shutdown() # end

setup.py에서 entry_points={‘console_scripts’: [],}, 안에 아래와 같이 넣고

entry_points={
        'console_scripts': [
            "test_node = my_robot_controller.my_first_node:main",
            "draw_circle = my_robot_controller.draw_circle:main",
            "pose_subscriber = my_robot_controller.pose_subscriber:main",
            "turtle_controller = my_robot_controller.turtle_controller:main"
        ],
    },

태그:

카테고리:

업데이트:

Comments