반응형
  1. 시작하기 전
    1. 앞선 글인 String토픽 생성을 기반으로 작성하였다.
    2. 기존 String전송과 차이점만 적어놓았으므로 처음이라면 아래의 글을 참고 하기 바란다.
      1. ROS2 패키지만들기-1(패키지 생성) (https://hostramus.tistory.com/112)
      2. ROS2 패키지만들기-2(노드생성 publisher) (https://hostramus.tistory.com/113)
      3. ROS2 패키지만들기-3(노드생성 Subscriber) (https://hostramus.tistory.com/114)
      4. ROS2 패키지만들기-4(확인 및 실행) (https://hostramus.tistory.com/115)
  2.  목표
    1. 2개의 정수를 퍼블리시하는 토픽 만들기
    2. std_msgs.msg의 Int8MultiArray 사용해보기
    3. 2개의 정수를 퍼블리시 하기
    4. 2개의 정수를 서브스크라이브하여 합계 계산하기
  3. 퍼블리셔 코드 (Publisher Code)
    import rclpy
    from rclpy import node
    from rclpy.node import Node
    from rclpy.qos import QoSProfile
    from std_msgs.msg import Int8MultiArray
    
    class HelloworldPublisher222(Node):
      def __init__(self):
        super().__init__('helloworld_publisher222')
        qos_profile = QoSProfile(depth=10)
        self.count = 0
        self.helloworld_publisher = self.create_publisher(Int8MultiArray, 'helloworld', qos_profile)
        self.timer = self.create_timer(1, self.publish_helloworld_msg)
    
      def publish_helloworld_msg(self):
        msg = Int8MultiArray()
        msg.data = [self.count, self.count+1]
        self.helloworld_publisher.publish(msg)
        self.get_logger().info('pub22 message: {0}'.format(msg.data))
        self.count += 1
    
    def main(args=None):
      rclpy.init(args=args)
      node = HelloworldPublisher222()
      try:
        rclpy.spin(node)
      except KeyboardInterrupt:
        node.get_logger().info('Keyboard Interrupt (SIGINT)')
      finally:
        node.destroy_node()
        rclpy.shutdown()
    
    if __name__ == '__main__':
      main()
    ​
  4. 코드 분석 (Publisher)
    1. from std_msgs.msg import Int8MultiArray
       
      1. 5행의 메세지 종류를 Int8MultiArray로 import한다.
      2. int8은 8비트정수로 -127~127까지 범위다
      3. int16, int32, int64중 원하는 크기로 사용한다.
    2. self.helloworld_publisher = self.create_publisher(Int8MultiArray, 'helloworld', qos_profile)
      1. 12행의 self.create_publisher에서 퍼블리시 할 형식을 기존 String대신 Int8Multiarray로 설정한다.
      2. 다른 것은 모두 그대로 놔둔다.
    3. msg = Int8MultiArray()
      msg.data = [self.count, self.count+1]
      1. 16행의 msg에 Int8MultiArray 인스턴스를 생성한다.
      2. 17행에서 msg.data의 값을 array형태로 만들어 넣는다.
        1. 여기에서는 count를 사용하였다.
  5. 서브스크라이버 코드 (Subscriber Code)
    import rclpy
    from rclpy.node import Node
    from rclpy.qos import QoSProfile
    from std_msgs.msg import Int8MultiArray
    
    class HelloworldSubscriber222(Node):
      def __init__(self):
        super().__init__('Helloworld_Subscriber222')
        qos_profile = QoSProfile(depth=10)
        self.helloworld_subscriber = self.create_subscription(Int8MultiArray, 'helloworld', self.subscribe_topic_message, qos_profile)
    
      def subscribe_topic_message(self, msg):
        b = msg.data[0]
        c = msg.data[1]
        self.get_logger().info('Receiced message: {0}'.format(msg.data))
        self.get_logger().info(str(b) + " + " + str(c) + " = " + str(b+c))
    
    def main(args=None):
      rclpy.init(args=args)
      node = HelloworldSubscriber222()
      try:
        rclpy.spin(node)
      except KeyboardInterrupt:
        node.get_logger().info('Keyboard Interrupt (SIGINT)')
      finally:
        node.destroy_node()
        rclpy.shutdown()
    
    if __name__ == '__main__':
      main()​
  6.  코드 분석 (Subscriber)
    1. from std_msgs.msg import Int8MultiArray​
       
      1. 4행에서 퍼블리셔와 같이 메세지 형식을 Int8MultiArray로 맞춰서 import한다.
    2. self.helloworld_subscriber = self.create_subscription(Int8MultiArray, 'helloworld', self.subscribe_topic_message, qos_profile)
      1.  10행에서 self.create_subscription에서 Int8MultiArray로 맞춰준다.
    3.   def subscribe_topic_message(self, msg):
          b = msg.data[0]
          c = msg.data[1]
          self.get_logger().info('Receiced message: {0}'.format(msg.data))
          self.get_logger().info(str(b) + " + " + str(c) + " = " + str(b+c))
      1. msg.data는 Array형태이다.
        1. b와 c에 msg.data[0]과 msg.data[1]의 데이터를 받는다.
      2. self.get_logger().info(str(b) + " + " + str(c) + " = " + str(b+c))
        1. self.get_logger().info()는 스트링타입을 인수로 받는다.
        2. 따라서 정수인 b,c를 str()을 이용하여 변환해준다.
  7. 실행
    1. 퍼블리셔 실행 화면
      1. self.count의 값이 array형태로 퍼블리시 되는것이 확인 된다.
      2. 위의 코드상 int8형식이기에 127이 넘어가는 순간 에러가 발생한다.
    2. 서브스크라이버 실행 화면
      1. 서브스크라이버는 받은 데이터(msg.data)를 한번 출력 후에 두 정수의 합계를 출력한다.

 

아래 출처의 내용을 수정 변경하였습니다.

개인적 공부를 위해 올린 글로 공부하실분은 아래 링크의 글을 참고하시기 바랍니다.

출처 : 오로카 카페 (cafe.naver.com/openrt/24450)

  1.  
반응형
반응형

ROS2 Foxy Fitzroy

 

패키지 노드(publisher) 만들기

 

 

1) ~/robot_ws/src/test1234/setup.py 확인

  1. 위의 경로 파일 재확인
    1. 내용을 모른다면 다시 1편으로
    2. hostramus.tistory.com/112\
 

ROS2 패키지 만들기 - 1 (패키지 생성)

ROS2 FOXY Fitzroy ROS2에서 패키지를 만들기 위한 방법 1) 패키지 생성 cd ~/robot_ws/src ros2 pkg create [패키지명] --build-type ament_python 이전에 만들어 놓은 ROS2 워크스페이스 src에 [패키지명]으로..

hostramus.tistory.com

 

2) 빌드

cd ~/robot_ws
colcon build --symlink-install
  1. 패키지를 생성했으니 빌드
    1. 패키지 생성 꼭 빌드 해야 사용이 가능
    2. --symlink-install
      1. 옵션 사항
      2. 빌드 후 파이썬 파일 수정을 해도 재빌드가 필요 없음
        1. 같은 파일 내에 수정일때 적용
        2. 빌드시 관련 파일(파이썬 등)을 링크로 연결하기에 쉽게 수정이 가능
        3. 결론.. 쓰면 편함

 

3) 노드 환경설정

. ~/robot_ws/install/local_setup.bash

#또는

source ~/robot_ws/install/local_setup.bash
  1. 노드 환경설정
    1. 그냥 한번 입력하면 별 반응도 없이 끝
    2. 출력되는 메세지조차 없음

 

4) 노드 실행

ros2 run test1234 hello_pub
  1. publisher 실행
    1. [INFO]: Published message: Hello World: 1
      1. 위와같이 1초에 하나씩 출력
ros2 run test1234 hello_sub
  1. subscriber 실행
    1. [INFO]: Received message: Hello World: 1
      1. 위와 같은 형식으로 출력
      2. 메세지가 날아올때만 출력

위와 같이 실행되면 완료

 

5) 문제 해결

  1. ros2 run test1234 hello_sub를 실행시켰으나 무반응
    1. 1번 setup.py의 entry points 내용 확인
    2. publisher와 subscriber의 파이썬 파일 확인
      1. 토픽명이 일치하는지 확인
    3. 코드의 오타 확인
  2. hello_suv등의 패키지를 찾지 못함 (탭을 눌렀으나 자동완성이 안되는 경우)
    1. source ~/robot_ws/install/local_setup.bash 실행한 후 확인

 

 

아래 출처의 내용을 수정 변경하였습니다.

개인적 공부를 위해 올린 글로 공부하실분은 아래 링크의 글을 참고하시기 바랍니다.

출처 : 오로카 카페 (cafe.naver.com/openrt/24450)

반응형
반응형

ROS2 Foxy Fitzroy

 

패키지 노드(publisher) 만들기



1) 파이썬 파일 생성

~/robot_ws/src/test1234/test1234
  1. 위 경로에 hello_sub.py 생성

 

2) 전체코드

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)  #QoS 설정

    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()  #HelloworldSubscriber 클래스 생성
    try:
        rclpy.spin(node)
    except KeyboardInterrupt:
        node.get_logger().info('Keyboard Interrupt (SIGINT)')
    finally:
        node.destroy_node()
        rclpy.shutdown()


if __name__ == '__main__':
    main()

코드 출처 : 오로카 카페 - 024 ROS프로그래밍 기초(python)_표윤석)

    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)  #QoS 설정
  1. self.helloworld_subscriber = self.create_subscription ~
    1. String : 메세지 타입
    2. 'helloworld' : 가져다 쓸 토픽 이름, 앞서 만든 publisher와 이름을 맞춰주어야 함
    3. self.subscribe_topic_message : 콜백 함수
    4. qos_prifile : QoS 설정
    def subscribe_topic_message(self, msg):
        self.get_logger().info('Received message: {0}'.format(msg.data))
  1. self.get_logger().info('Received message: {0}'.format(msg.data))
    1. 데이터가 들어오면 'msg.data'의 값을 '{0}'에 넣어 콘솔창에 출력
def main(args=None):
    rclpy.init(args=args)
    node = HelloworldSubscriber()  #HelloworldSubscriber 클래스 생성
    try:
        rclpy.spin(node)
    except KeyboardInterrupt:
        node.get_logger().info('Keyboard Interrupt (SIGINT)')
    finally:
        node.destroy_node()
        rclpy.shutdown()
  1. node = HelloworldSubscriber() : HelloworldSubscriber 클래스 생성
  2. rclpy.spin(node) : ROS에 노드 spin

 

3) 결론

  1. 특별한 것 없음
  2. publisher와의 차이는 12행에서 'create_publisher', 'create_subscription'만 다르다

 

반응형
반응형

ROS2 Foxy Fitzroy

 

패키지 노드(publisher) 만들기

 

 

1) 파이썬 파일 생성

~/robot_ws/src/test1234/test1234
  1. 위의 경로에 'hello_pub.py'를 생성

 

 

2) 전체 코드

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)  #QoS 설정, 큐 사이즈 10(10개의 데이터 보관)
        self.helloworld_publisher = self.create_publisher(String, 'helloworld', qos_profile)  #qos_profile속성으로 publisher 생성
        self.timer = self.create_timer(1, self.publish_helloworld_msg)  #timer tick(1초)마다 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))  #logger에 메세지 기록
        self.count += 1


def main(args=None):
    rclpy.init(args=args)
    node = HelloworldPublisher()  #클래스 실행
    try:
        rclpy.spin(node)  #ROS에 노드 spin, 프로그램 종료까지 반복
    except KeyboardInterrupt:
        node.get_logger().info('Keyboard Interrupt (SIGINT)')  #종료시 logger에 기록
    finally:
        node.destroy_node()  #노드 종료
        rclpy.shutdown()  #rclpy 종료


if __name__ == '__main__':
  main()

(코드 출처 : 오로카 카페 - 024 ROS프로그래밍 기초(python)_표윤석)

 

    def __init__(self):
        super().__init__('helloworld_publisher')
        qos_profile = QoSProfile(depth=10)  #QoS 설정, 큐 사이즈 10(10개의 데이터 보관)
        self.helloworld_publisher = self.create_publisher(String, 'helloworld', qos_profile)  #qos_profile속성으로 publisher 생성
        self.timer = self.create_timer(1, self.publish_helloworld_msg)  #timer tick(1초)마다 publish_helloworld_msg 실행
        self.count = 0
  1. qos_profile = QoSProfile(depth=10)
    1. QoS 설정
    2. 데이터를 보관해 놓을 큐의 사이즈 지정 (depth=10)
    3. 오로카 ROS 강의 참고 (https://cafe.naver.com/openrt/24319)
  2. self.helloworld_publisher = self.create_publisher(String, 'helloworld', qos_profile)
    1. self.helloworld_publisher : helloworld_publisher라는 이름으로 노드 이름 지정
    2. String : 메세지 타입
    3. 'helloworld' : 토픽 이름
    4. qos_profile : QoS 설정 (현재 큐 사이즈 10으로 설정)
    5. self.timer = self.create_timer(1, self.publish_helloworld_msg) : 타이머를 생성하여 1초에 한번씩 publish_helloworld_msg 실행

 

    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))  #logger에 메세지 기록
        self.count += 1
  1. msg = String() : 메세지를 스트링 타입으로 지정
  2. msg.data = 'Hello world : {0}'.format(self.count) : 메세지 내용 지정
  3. self.helloworld_publisher.publish(msg) : 메세지 전송
  4. self.get_logger().info('Published message : {0}'.format(msg.data)) : 메세지 내용을 콘솔창에 출력

 

def main(args=None):
    rclpy.init(args=args)
    node = HelloworldPublisher()  #클래스 실행
    try:
        rclpy.spin(node)  #ROS에 노드 spin, 프로그램 종료까지 반복
    except KeyboardInterrupt:
        node.get_logger().info('Keyboard Interrupt (SIGINT)')  #종료시 logger에 기록
    finally:
        node.destroy_node()  #노드 종료
        rclpy.shutdown()  #rclpy 종료
  1. rclpy.init(args=args) : 초기화
  2. node = HelloworldPublisher() : 클래스 실행
  3. rclpy.spin(node) : ROS에 노드 spin, 프로그램 종료까지 반복
  4. node.destroy_node() : 노드 종료
  5. rclpy.shutdown() : rclpy 종료

 

3) 결론

  1. 중요 핵심 사항만 있는 코드
  2. 이것만으론 뭘 못하니 여기서 추가 내용을 짜서 공부 할 것
  3. 아래 표시한곳들만 서로 맞춰주면 문제 없음

 

 

아래 출처의 내용을 수정 변경하였습니다.

개인적 공부를 위해 올린 글로 공부하실분은 아래 링크의 글을 참고하시기 바랍니다.

출처 : 오로카 카페 (cafe.naver.com/openrt/24450)

 

 

 

반응형
반응형

ROS2 FOXY Fitzroy

 

ROS2에서 패키지를 만들기 위한 방법

 

 

1) 패키지 생성

cd ~/robot_ws/src
ros2 pkg create [패키지명] --build-type ament_python
  1. 이전에 만들어 놓은 ROS2 워크스페이스 src에 [패키지명]으로 패키지를 생성
  2. '--build-type ament_python'
    1. 파이썬으로 패키지를 생성할것이기에 ament_python으로 빌드하도록 설정
  3. src 폴더내에 [패키지명]으로 된 폴더가 생성됨
  4. ros2 pkg create [패키지명] --build-type ament_python --dependencies rclpy std_msgs
    1. 패키지 생성시 의존성을 한번에 설정하는 방법
      1. 현재 rclpy와 std_msgs가 추가됨
      2. 아래 package.xml에서 설명

 

2) package.xml 설정

# 기본 생성 파일

<?xml version="1.0"?>
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
<package format="3">
  <name>test1234</name>
  <version>0.0.0</version>
  <description>TODO: Package description</description>
  <maintainer email="lee@todo.todo">lee</maintainer>
  <license>TODO: License declaration</license>

  <test_depend>ament_copyright</test_depend>
  <test_depend>ament_flake8</test_depend>
  <test_depend>ament_pep257</test_depend>
  <test_depend>python3-pytest</test_depend>

  <export>
    <build_type>ament_python</build_type>
  </export>
</package>

 

  1. 의존 패키지
    1. 의존 패키지 내용을 적는 부분
    2. 실행시킬 패키지가 사용하는 라이브러리라 생각하면 됨
    3. 위의 패키지 생성에서 뒤에 '--dependencies rclpy std_msgs'를 붙인 경우 이미 의존 패키지 설정이 되어 있음
  2. 빌드 타입
    1. 우린 파이썬으로 만들것이기에 빌드 타입이 'ament_python'으로 설정되어 있음
      1. 위에서 '--build-type ament_python'으로 설정되었기에 건드릴것 없음
  3. 포인트
    1. 의존 패키지 내용 잘 확인 할것
      1. 위에 패키지 생성시 안적었으면 여기다 적으면 됨
    2. 빌드 타입 확인 할 것
      1. 파이썬인지 cpp(ament_cmake)인지 확인 할 것

 

3) setup.py

# 기본 내용

from setuptools import setup

package_name = 'test1234'

setup(
    name=package_name,
    version='0.0.0',
    packages=[package_name],
    data_files=[
        ('share/ament_index/resource_index/packages',
            ['resource/' + package_name]),
        ('share/' + package_name, ['package.xml']),
    ],
    install_requires=['setuptools'],
    zip_safe=True,
    maintainer='lee',
    maintainer_email='lee@todo.todo',
    description='TODO: Package description',
    license='TODO: License declaration',
    tests_require=['pytest'],
    entry_points={
        'console_scripts': [
        ],
    },
)
  1. entry_points
    1. 여기에 패키지 노드 이름 작성
      1. 나중에 실행시 ros2 run test1234 hello_pub 또는 ros2 run test1234 hello_sub 로 실행
    2. 노드 이름과 파이썬 파일을 연결

 

4) 결론

  1.  패키지 생성
    1. 어려울것 없음
    2. 실수로 옵션 빼먹어도 package.xml에서 수정 가능
      1. 단 '--build-type ament_python'빼먹으면 패키지 폴더내에 생성되는 파일이 다름
      2. 잘 확인해서 생성할것
  2.  package.xml
    1. 의존 패키지 확인이 매우 중요
    2. 나머지 내용은 저작자, 라이센스 등 부수적 내용
      1. 추후에 찾아서 배포판을 만들시 자세히 작성
  3. setup.py
    1. 'entry_points'에 사용할 노드명, 경로 잘 입력할 것

 

 

아래 출처의 내용을 수정 변경하였습니다.

개인적 공부를 위해 올린 글로 공부하실분은 아래 링크의 글을 참고하시기 바랍니다.

출처 : 오로카 카페 (cafe.naver.com/openrt/24450)

반응형

+ Recent posts