# 04장 Build system

* 77Creating a launch file

<https://index.ros.org/doc/ros2/Tutorials/Launch-Files/Creating-Launch-Files/#ros2launch>

* Writing a simple publisher and subscriber (Python)

<https://index.ros.org/doc/ros2/Tutorials/Writing-A-Simple-Py-Publisher-And-Subscriber/#pypubsub>

* Writing a simple publisher and subscriber (C++)

<https://index.ros.org/doc/ros2/Tutorials/Writing-A-Simple-Cpp-Publisher-And-Subscriber/#cpppubsub>\
\
발표자 : 권준호, 김효민참석자 : 최규남, 류정필, 이태용, 김효민,김경남,박정은,안지훈, 김진성, 이창환, Yu Minsang,SANGYONG, 최종우,정하정

## + Build system 1-1

ROS2를 사용하기전에 작업환경을 구축함.실행을 하기전에 ROS2가 설치 되어있어야 함.

기본자료&#x20;

<https://www.theconstructsim.com/ros2-in-5-mins-007-how-to-create-a-ros2-overlay-workspace/>                  <https://index.ros.org/doc/ros2/Tutorials/Workspace/Creating-A-Workspace/#ros2workspace><br>

#### 디렉토리생성

```
$ mkdir -p ros2_ws/src && cd ros2_ws
```

위 코드를 입력하게 되면 다음과 같이 ros2\_ws이름의 디렉토리가가 생성 및  디렉토리 안으로 들어가는 것을 볼 수 있음

![Selection\_108.png](https://coda.io/contentProxy/w_N8GLWiAl/blobs/bl-XDqI1tk0Ki/8913cdd7f33360e5d053bc3fdc7c1af36cc02243262c35e7ac7e73e8cdb6dc02e8c9a4541f25b9f0365ed5d06d25c677fa9a6d6c062b2e8cf3d9bd258f71e6136de1b83072ee37a14ffc2f5f6490a69b9012b0654ab1accdebdbedb83fb8b621a2878886)

#### colcon에 대하여

colcon 은  ROS를 위한 범용 빌드 툴로서 개발되고 있는 툴이다. 이 툴은 ROS1, ROS2, 비 ROS 소프트웨어까지 모두 포괄하여 사용할 수 있도록 설계되었고, 기존에 설명한 catkin\_make, catkin\_make\_isolated, catkin\_tools, ament\_tools 의 모든 기능을 사용 할 수 있도록 개발되고 있다.<br>

#### colcon사용법

colcon 사용법 및 옵션들은 기존 툴들과 호환된다. 그 사용법에 대한 설명은 아래의 링크로 대신한다. 원론적으로 왜 이 범용 빌드 툴이 나오게 되었는지에 대한 고민과 의견 수렴에 대해서는 사용자 입장에서는 그렇게 크게 중요하지 않다고 생각한다. 우리에게 더 중요한 자세한 사용 방법은 이어지는 ROS2 실제 프로그래밍에서 더 깊숙히 파헤쳐 보도록 하자.\
\
&#x20;<https://cafe.naver.com/openrt/18732> <http://design.ros2.org/articles/build_tool.html> <http://colcon.readthedocs.io/> <https://github.com/colcon> <https://github.com/ros2/ros2/wiki/Colcon-Tutorial> <https://colcon.readthedocs.io/en/latest/migration/ament_tools.html> <https://colcon.readthedocs.io/en/latest/migration/catkin_make_isolated.html> <https://colcon.readthedocs.io/en/latest/migration/catkin_tools.html><br>

```
$ colcon build
```

위의 코드를 입력 하게 되면 다음과 같이 나타나는것을 볼 수 있다

![Selection\_106.png](https://coda.io/contentProxy/w_N8GLWiAl/blobs/bl-hF9lbXgE1B/dea7856e27698c7d7d51752722d1a04d04ed75c3f95a97732957fc39a9a1c89be23b95c21d8c4944fe1732881a1051ec963ec5c224537262869687cabf74ca62d650999118d8799f22f2a3d9908d0a015b7c00f8906d69d01affcff4ebfa605c3c4e6df2)

**다만, 처음 colcon build를 입력하게 된다면 오류 메시지가 뜰 수 있다.** **이 경우**

`$ sudo apt install python3-colcon-common-extensions`를 통해 해결할 수 있다.

ll (ls-l) 를 입력하여 현재 디렉토리의 자세한 내용을 알아보자

![Selection\_109.png](https://coda.io/contentProxy/w_N8GLWiAl/blobs/bl-I3Dxys_GC3/e84b8d60904960c0f38758b134b2efa79423a3ff692d229eaa5791c0fe1bcab7abbe5bd88d03c17058a52ae319c754c1fb267c9c39c73672a972beadd9c9d443506c6f86108a791797bccb8df38f8d0a6941f1e2e476a3d36aad4decf6495fa87bea243d)

마지막으로  다음 자료를 다운 받으면 기초적인  개발환경 구축이  완료된다.

```
$ source install/local_setup.bash && source install/setup.bash
```

## + Build system 1-2

\
빌드에 앞서 다음 코드를 이용해  설치 한다.

```
$ sudo apt install git-all
$ sudo apt update
```

#### 디렉토리 생성

먼저 dev\_ws(development workspace) 라는 이름의 디렉토리를 생성후 디렉토리에 접속해보자.

```
$ mkdir dev_ws
$ mkdir dev_ws/src
$ cd dev_ws/src
```

#### 샘플복제

샘플을 복제하기전 dev\_ws/src에 들어가 있어야 함. dev\_ws/src디렉토리에 들어가 있을 경우, 다음 명령어를 통해 ros\_tutorials를 복제해 보자

```
$ git clone https://github.com/ros/ros_tutorials.git -b eloquent-devel
```

이렇게 복제를 완료한 뒤에  ros\_tutorials list를 확인해 보면 다음과 같이 나타나는 것을 볼 수 있다.

![Selection\_114.png](https://coda.io/contentProxy/w_N8GLWiAl/blobs/bl-Q7DSTtoeM1/090535b562bf391181bf821241cfbff085d150cd975e0f27fa42850578dfc08cc9ff84916ce3d1b9a30ad54d8e99071e57e61b0fc082d33bf781e6f0140478f786f2b90347723c3a603223d4ff157916833e6e0c0da8d87c97e624d5aea0b2dd580624c3)

```
$ cd dev_ws/src
$ ls ros_tutorials
```

작업 공간을 샘플 패키지로 채웠으나 아직 완전히 작동하는 작업 공간은 아니다. 종속성을 해결하고 작업 공간을 먼저 구축해야 한다.

#### **패키지 종속 해결**

작업 공간을 구축하기 전 패키지 종속성을 해결해야 한다. 이미 모든 종속성을 가지고 있을 수 있지만, 최선의 방법은 복제할 때마다 종속성을 확인하는 것이다.

다음의 명령을 통해  종속을 해결할 수 있다.

```
$ sudo rosdep install -i --from-path src --rosdistro dashing -y
```

다만 그 전에 rosdep가 설치되어있지 않다면 정상적으로 작동되지 않을것이다다음과 같이 ros dep 를 설치하자

```
$ sudo apt-get install python-rosdep
$ sudo rosdep init
$ rosdep update
```

![Selection\_116.png](https://coda.io/contentProxy/w_N8GLWiAl/blobs/bl-IA3ywiamOQ/ff3dce5f7765845aaff4183834bb741bc9fd065ad51e8339261ab5448e7067f2bd3768a9fdf4bb91cfe6a05d337e045e7b4f0d6e81c8eed868f49ce2c2c5f34909d6c8b6c5321a528a2cd51bab834f137016e533d7ce2b47e33bfb66f289df5fa852f104)

#### **colcon build를 통해 작업환경 구축**

이후 colcon build를 이용하여 명령을 내리면 다음과 같은 결과를 얻을 수 있다.<br>

![Selection\_113.png](https://coda.io/contentProxy/w_N8GLWiAl/blobs/bl-URw659FW-Z/3685e301e4e19b6a623ed2a6f296d2ddbc1ded7dfa2b28574fde5428f1d998c21bdb619012f23b00ecf12661602428f9421bf9b534546bbf36fb7b3cc914f5cd8d268a47a64ad89c9aeddea9441d7e3141a71a0f4aec5da1590ac80dbdf47ec1b693e358)

#### **Overlay 수정**

turtlesim 창의 제목 표시줄을 편집하여 오버레이에서 turtlesim을 수정할 수 있다. 다음의 디렉토리 내에서 turtle\_frame.cpp텍스트를 수정해보자.

```
$ cd dev_ws/src/ros_tutorials/turtlesim/src
$ gedit turtle_frame.cpp
```

**turtle\_frame.cpp텍스트에 들어갔다면** **setWindowTitle("TurtleSim")** **의** **”TurtleSim”** **을** **”MyTurtleSim”** **로 수정하고 저장하자**

```
#include "turtlesim/turtle_frame.h"

#include <QPointF>

#include <cstdlib>
#include <ctime>

#define DEFAULT_BG_R 0x45
#define DEFAULT_BG_G 0x56
#define DEFAULT_BG_B 0xff
https://www.icbanq.com/A03_webinar/B01_webiWork/seminar_view.do?seminar_number=403https://www.icbanq.com/A03_webinar/B01_webiWork/seminar_view.do?seminar_number=403
namespace turtlesim
{

TurtleFrame::TurtleFrame(rclcpp::Node::SharedPtr& node_handle, QWidget* parent, Qt::WindowFlags f)
: QFrame(parent, f)
, path_image_(500, 500, QImage::Format_ARGB32)
, path_painter_(&path_image_)
, frame_count_(0)
, id_counter_(0)
{
  setFixedSize(500, 500);
  setWindowTitle("TurtleSim");

  srand(time(NULL));

  update_timer_ = new QTimer(this);
  update_timer_->setInterval(16);
  update_timer_->start();

  connect(update_timer_, SIGNAL(timeout()), this, SLOT(onUpdate()));

  nh_ = node_handle;
  rcl_interfaces::msg::IntegerRange range;
  range.from_value = 0;
  range.to_value = 255;
 중략..._value = 255;
```

```
 중략...
```

이후 이전에 colcon build를 실행한 터미널 창으로 돌아가 colcon build를 재실행한다. 다음을 통해 주 ROS 2 환경을 "언더레이"로 제공하므로 오버레이를 "위에" 구축할 수 있다

```
$ source /opt/ros/dashing/setup.bash
```

그후 dev\_ws디렉토리에서 오버레이를 소싱한다

```
$. install/local_setup.bash
```

그 다음 터틀심을 실행하면 창의 이름이 바뀌어 있다는것을 확인할 수 있다.하지만 언더레이가 여전히 손상되지 않았는지 확인하려면 새 터미널을 열고 다시 실행해보면 원래대로 돌아오는것을 알 수 있다.![Selection\_117.png](https://coda.io/contentProxy/w_N8GLWiAl/blobs/bl-ouryIJ-cpE/fc83ff18b7c70a96e8a04a096c27f4515da88482f163bc4025225b25904cb535ae9dc7b6a18a3dd9213e859073e680243d3a59d2659c4a30fd6733d6078ad0b6e754e7ce1b445b4daebc546a1b26b31157eb9bbfc8773895ec5da95905ba3c4e2a8f0edd)\ <br>

## + Creating a launch file

\
노드를 실행할 때 마다 terminal을 새로 열어서 실행을 한다는 것은 귀찮은 일임.여러노드를 한번에 열수 있게 Launch file을 제공함.

```
$ mkdir launch
$ touch turtlesim_mimic_launch.py
```

### turtlesim\_mimic\_launch.py

```
from  launch import LaunchDescription
from launch_ros.actions import Node

def generate_launch_description():
    return LaunchDescription([
        Node(
            package='turtlesim',
            node_namespace='turtlesim1',
            node_executable='turtlesim_node',
            node_name='sim'
        ),
        Node(
            package='turtlesim',
            node_namespace='turtlesim2',
            node_executable='turtlesim_node',
            node_name='sim'
        ),
        Node(
            package='turtlesim',
            node_executable='mimic',
            node_name='mimic',
            remappings=[
                ('/input/pose', '/turtlesim1/turtle1/pose'),
                ('/output/cmd_vel', '/turtlesim2/turtle1/cmd_vel'),
            ]
        )
    ])
```

위의 sim node가 동일해 보이지만 node\_namespace로 구분되기 때문에 괜찮음.

<https://github.com/ros/ros_tutorials/blob/melodic-devel/turtlesim/tutorials/mimic.cpp>

mimic node의 경우 remapping을 사용하는 것을 살펴보면,mimic의 /input/pose topic을 /turtlesim1/turtle1/pose로 /output/cmd\_vel topic을 /turtlesim2/turtle1/cmd\_vel로 재설정 함.

결국 /turtlesim1/turtle1/pose(위치)가 mimic의 /input/pose 입력으로 들어가고 mimic의 출력 /output/cmd\_vel(속도)이 /turtlesim2/turtle1/cmd\_vel로 연결된다.

```
$ ros2 launch turtlesim_mimic_launch.py
```

\* 실행시 turtlesim이 설치되어 있어야 동작 되는 것으로 보임.

```
$ sudo apt install ros-dashing-turtlesim
```

rqt\_graph로 현재 node의 관계를 좀더 직관적으로 살펴볼수 있다.

```
$ rqt_graph
```

실제 동작을 확인해 보자.

```
$ ros2 topic pub -r 1 /turtlesim1/turtle1/cmd_vel geometry_msgs/msg/Twist '{linear: {x: 2.0, y: 0.0, z: 0.0}, angular: {x: 0.0, y: 0.0, z: -1.8}}'
```

![](https://lh3.googleusercontent.com/vi_I0puNxfQj7KFpfWJU0vYElstCja_Uv1zquk51HypkGeEf8S0iL5kZTMVq0RGssgs1ebyBxL70vGt69rtw2DpGyl4Wrf6htY9psLKtKdCKKBz0mhihJiO_hph1ad8jDbG_gS81)

rqt\_graph에 Group을 0으로 설정하면 예와 동일하게 출력됨.

![](https://lh4.googleusercontent.com/0RrD93gornUI4K-J5YUygcE2r8p_EFMs0sYl2zHPEZP7qilIP8Ij9sU0ME4NakDjb8GQyY-39afqLyk-8ObDYG9uq4Ic9CEJjBoJH5EoVFfpMGvQ8NkbBcijpXnWyB97EVqb_voQ)

## + Creating a ROS 2 package

기본 자료 : <https://index.ros.org/doc/ros2/Tutorials/Creating-A-ROS2-Package/#createpkg><br>

#### 패키지에 대하여

패키지는  ROS 2 코드를 위한 컨테이너라고 생각할 수 있다. 만약 코드를 설치하거나 다른 사람들과 공유할 수 있기를 원한다면, 그것을 패키지로 정리해야 한다. 이것으로,  자신의 작품을 공유할 수 있고 다른 사람들이 그것을 쉽게 만들고 사용할 수 있게 할 수 있다.\
ROS 2의 패키지 생성은 ament를 빌드 시스템으로, colcon을 빌드 도구로 사용한다. 다른 빌드 유형이 존재하나 공식적으로 지원되는 CMake 또는 Python을 사용하여 패키지를 생성할 수 있다.<br>

#### **패키지 생성**

다음과 같이 dev\_ws/src 디렉토리 내에서 패키지를 생성한다

```
$ ros2 pkg create --build-type ament_cmake --node-name my_node my_package
```

이 튜토리얼의 경우 패키지에 간단한 Hello World 유형 실행 파일을 생성하는 선택적 인수 --node-name을 사용한다. 다음의 명령어를 통해 본 메시지를 받게된다.이 를통해 새 패키지에 대해 자동으로 생성된 파일을 볼 수 있다

![Selection\_118.png](https://coda.io/contentProxy/w_N8GLWiAl/blobs/bl-lKhardhsV7/15e34c87db89c6ca53c51cbd4b9d342e0a4b502cc12d1b21c2c1953e69e96331e07a6d4bab255b59f26422cee91bae8d8ad8298184ae4709278188142e5d582cb3455b9a46ee7e1370b0f8ec29ad88d5a7550cb963b25449afa8b5c585fa70b65986a5cc)

#### 패키지 구축

작업영역에 패키지를 넣는 것은 작업영역 루트에서 콜콘 빌드를 실행하여 한 번에 많은 패키지를 만들 수 있기 때문에 특히 중요하다. 그렇지 않으면 각 패키지를 개별적으로 만들어야 할 것이다.

**다음 번에 my\_package 패키지만 구축하려면 다음을 실행하십시오.**

```
$ colcon build --packages-select my_package
```

**그런 다음 dev\_ws 디렉터리 내부에서 다음 명령을 실행하여 작업 공간을 소싱한다.**

```
$ . install/setup.bash
```

이제 작업 공간이 경로에 추가되었으므로 새 패키지의 실행 파일을 사용할 수 있다.\
패키지 생성 중 --node-name 인수를 사용하여 생성한 실행 파일을 실행하려면 다음 명령을 입력한다.

```
$ ros2 run my_package my_node
```

그결과 다음과 같은 메시지를 받게 된다.\
\
dev\_ws/src/my\_package 내부에는 자동으로 생성된 2pkg의 파일과 폴더가 표시된다.

![Selection\_119.png](https://coda.io/contentProxy/w_N8GLWiAl/blobs/bl-xp9xWTdp2g/c3448c609f3d6fd2dd6bd9d96e31d6acf9ebdf742964f8b075772edf10584e15338608ebac97f5a8247869432df838deb3153148c38e612f7d4d88df5ef607dd1a070946e40756f1170604a133b2715a32f6682fa4bf1566fffac203eca69a90f04d1ab3)

```
CMakeLists.txt  include  package.xml  src
 Customize 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>my_package</name>
 <version>0.0.0</version>
 <description>TODO: Package description</description>
 <maintainer email="user@todo.todo">user</maintainer>
 <license>TODO: License declaration</license>

 <buildtool_depend>ament_cmake</buildtool_depend>

 <test_depend>ament_lint_auto</test_depend>
 <test_depend>ament_lint_common</test_depend>

 <export>
   <build_type>ament_cmake</build_type>
 </export>
</package>
```

**내용중 7번 라인이자동으로 채워지지 않은 경우 7번 라인에 이름과 이메일을 입력하십시오. 그런 다음 라인 6에서 다음 설명을 편집하여 패키지를 요약한다.**

```
<description>Beginner developer tutorials practice package</description>
```

**그다음, 다음과 같이 8번라인의 라이센스를 업데이트한다**

```
<license>Apache License 2.0</license>
```

라이센스 태그 아래에 \_depended로 끝나는 태그 이름이 있다. 여기가  package.xml이 colcon을 검색할 다른 패키지에 대한 의존성을 나열할 것이다. my\_package는 단순하고 의존성이 전혀 없지만 이 공간이 다가오는 튜토리얼에서 활용되고 있는 것을 볼 수 있을 것이다.<br>

## + Writing a simple publisher and subscriber (Python)

\
**topic으로 string message를 처리하는 node를 작성한다.**

| **rclpy**                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| <http://docs.ros2.org/eloquent/api/rclpy/>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| <p><strong>create\_publisher</strong>(msg\_type, topic, qos\_profile, \*, callback\_group=None, event\_callbacks=None)Create a new publisher.<strong>Parameters</strong></p><ul><li><strong>msg\_type</strong> – The type of ROS messages the publisher will publish.</li><li><strong>topic</strong> (<strong>str</strong>) – The name of the topic the publisher will publish to.</li><li><strong>qos\_profile</strong> (<strong>Union</strong>\[<a href="http://docs.ros2.org/eloquent/api/rclpy/api/qos.html#rclpy.qos.QoSProfile">QoSProfile</a>, <strong>int</strong>]) – A QoSProfile or a history depth to apply to the publisher. In the case that a history depth is provided, the QoS history is set to RMW\_QOS\_POLICY\_HISTORY\_KEEP\_LAST, the QoS history depth is set to the value of the parameter, and all other QoS settings are set to their default values.</li><li><strong>callback\_group</strong> (<strong>Optional</strong>\[<a href="http://docs.ros2.org/eloquent/api/rclpy/api/execution_and_callbacks.html#rclpy.callback_groups.CallbackGroup">CallbackGroup</a>]) – The callback group for the publisher’s event handlers. If None, then the node’s default callback group is used.</li><li><strong>event\_callbacks</strong> (<strong>Optional</strong>\[<strong>PublisherEventCallbacks</strong>]) – User-defined callbacks for middleware events.</li></ul><p><strong>Return type</strong><a href="http://docs.ros2.org/eloquent/api/rclpy/api/topics.html#rclpy.publisher.Publisher">Publisher</a><strong>Returns</strong>The new publisher.</p>                                                                                                                                                                                                                                                                                                                        |
| <p><strong>create\_subscription</strong>(msg\_type, topic, callback, qos\_profile, \*, callback\_group=None, event\_callbacks=None, raw=False)Create a new subscription.<strong>Parameters</strong></p><ul><li><strong>msg\_type</strong> – The type of ROS messages the subscription will subscribe to.</li><li><strong>topic</strong> (<strong>str</strong>) – The name of the topic the subscription will subscribe to.</li><li><strong>callback</strong> (<strong>Callable</strong>\[\[\~MsgType], None]) – A user-defined callback function that is called when a message is received by the subscription.</li><li><strong>qos\_profile</strong> (<strong>Union</strong>\[<a href="http://docs.ros2.org/eloquent/api/rclpy/api/qos.html#rclpy.qos.QoSProfile">QoSProfile</a>, <strong>int</strong>]) – A QoSProfile or a history depth to apply to the subscription. In the case that a history depth is provided, the QoS history is set to RMW\_QOS\_POLICY\_HISTORY\_KEEP\_LAST, the QoS history depth is set to the value of the parameter, and all other QoS settings are set to their default values.</li><li><strong>callback\_group</strong> (<strong>Optional</strong>\[<a href="http://docs.ros2.org/eloquent/api/rclpy/api/execution_and_callbacks.html#rclpy.callback_groups.CallbackGroup">CallbackGroup</a>]) – The callback group for the subscription. If None, then the nodes default callback group is used.</li><li><strong>event\_callbacks</strong> (<strong>Optional</strong>\[<strong>SubscriptionEventCallbacks</strong>]) – User-defined callbacks for middleware events.</li><li><strong>raw</strong> (<strong>bool</strong>) – If True, then received messages will be stored in raw binary representation.</li></ul><p><strong>Return type</strong><a href="http://docs.ros2.org/eloquent/api/rclpy/api/topics.html#rclpy.subscription.Subscription">Subscription</a></p> |
| <p>rclpy.<strong>spin</strong>(node, executor=None)Execute work and block until the context associated with the executor is shutdown.Callbacks will be executed by the provided executor.This function blocks.<strong>Parameters</strong></p><ul><li><strong>node</strong> (<a href="http://docs.ros2.org/eloquent/api/rclpy/api/node.html#rclpy.node.Node">Node</a>) – A node to add to the executor to check for work.</li><li><strong>executor</strong> (<a href="http://docs.ros2.org/eloquent/api/rclpy/api/execution_and_callbacks.html#rclpy.executors.Executor">Executor</a>) – The executor to use, or the global executor if None.</li></ul><p><strong>Return type</strong>None</p>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| **publish**(msg)Send a message to the topic for the publisher.**Parametersmsg** (\~MsgType) – The ROS message to publish.**Raises**TypeError if the type of the passed message isn’t an instance of the provided type when the publisher was constructed.**Return type**None                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |

```
$ ros2 pkg create --build-type ament_python py_pubsub

$ wget https://raw.githubusercontent.com/ros2/examples/master/rclpy/topics/minimal_publisher/examples_rclpy_minimal_publisher/publisher_member_function.py 

$ wget 
https://raw.githubusercontent.com/ros2/examples/master/rclpy/topics/minimal_subscriber/examples_rclpy_minimal_subscriber/subscriber_member_function.py 

$ ls
__init__.py  publisher_member_function.py

$ tree
.
├── package.xml
├── py_pubsub
│   ├── __init__.py
│   ├── publisher_member_function.py
│   └── subscriber_member_function.py
├── resource
│   └── py_pubsub
├── setup.cfg
├── setup.py
└── test
    ├── test_copyright.py
    ├── test_flake8.py
    └── test_pep257.py
```

| publisher\_member\_function.py                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Column 1                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
| <p>import rclpyfrom rclpy.node import Node<br>from std\_msgs.msg import String<br><br><strong>class</strong> <strong>MinimalPublisher</strong>(Node):<strong>=> Node를 상속받아서 새로운 class를 생성</strong><br>    <strong>def</strong> **init**(self):        super()<strong>.</strong>**init**('minimal\_publisher')        <strong>=> 부모 class에게 현재 Node name 전달</strong><br>        self<strong>.</strong>publisher\_ <strong>=</strong> self<strong>.</strong>create\_publisher(String, 'topic', 10)        <strong>=> node publisher가 Message type String을 사용하고 ‘topic’ 이라는 topic name을 사용하며 queue의 크기 10 으로 정의함.</strong><br>        timer\_period <strong>=</strong> 0.5  # seconds        self<strong>.</strong>timer <strong>=</strong> self<strong>.</strong>create\_timer(timer\_period, self<strong>.</strong>timer\_callback)        <strong>=> 0.5초 마다 callback 함수를 호출하도록 timer 설정</strong><br>        self<strong>.</strong>i <strong>=</strong> 0<br>    <strong>def</strong> <strong>timer\_callback</strong>(self):        msg <strong>=</strong> String()        msg<strong>.</strong>data <strong>=</strong> 'Hello World: %d' <strong>%</strong> self<strong>.</strong>i <strong>=> message 정의</strong><br>        self<strong>.</strong>publisher\_<strong>.</strong>publish(msg) <strong>=> message 전송</strong><br>        self<strong>.</strong>get\_logger()<strong>.</strong>info('Publishing: "%s"' <strong>%</strong> msg<strong>.</strong>data) <strong>=> console에 출력</strong><br>        self<strong>.</strong>i <strong>+=</strong> 1<br><br><strong>def</strong> <strong>main</strong>(args<strong>=None</strong>):    rclpy<strong>.</strong>init(args<strong>=</strong>args)<br>    minimal\_publisher <strong>=</strong> MinimalPublisher()<br>    rclpy<strong>.</strong>spin(minimal\_publisher)<br>    # Destroy the node explicitly    # (optional - otherwise it will be done automatically    # when the garbage collector destroys the node object)    minimal\_publisher<strong>.</strong>destroy\_node()    rclpy<strong>.</strong>shutdown()<br><br><strong>if</strong> **name** <strong>==</strong> '**main**':    main()</p> |

|                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Column 1                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
| <p>import rclpyfrom rclpy.node import Node<br>from std\_msgs.msg import String<br><br><strong>class</strong> <strong>MinimalSubscriber</strong>(Node):<strong>=> Node를 상속받아서 새로운 class를 생성</strong><br>    <strong>def</strong> **init**(self):        super()<strong>.</strong>**init**('minimal\_subscriber')        self<strong>.</strong>subscription <strong>=</strong> self<strong>.</strong>create\_subscription(            String,            'topic',            self<strong>.</strong>listener\_callback,            10) <strong>=> create\_publish()와의 차이점은 message 수신시 대응할 callback 함수만 연결해 주면 된다.</strong>        self<strong>.</strong>subscription  # prevent unused variable warning<br>    <strong>def</strong> <strong>listener\_callback</strong>(self, msg):        self<strong>.</strong>get\_logger()<strong>.</strong>info('I heard: "%s"' <strong>%</strong> msg<strong>.</strong>data) <strong>=> 수신한 message를 console에 출력함.</strong><br><strong>def</strong> <strong>main</strong>(args<strong>=None</strong>):    rclpy<strong>.</strong>init(args<strong>=</strong>args)<br>    minimal\_subscriber <strong>=</strong> MinimalSubscriber()<br>    rclpy<strong>.</strong>spin(minimal\_subscriber)<br>    # Destroy the node explicitly    # (optional - otherwise it will be done automatically    # when the garbage collector destroys the node object)    minimal\_subscriber<strong>.</strong>destroy\_node()    rclpy<strong>.</strong>shutdown()<br><br><strong>if</strong> **name** <strong>==</strong> '**main**':    main()</p> |

|                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Column 1                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
| <p>\<?xml version="1.0"?>\<?xml-model href="<http://download.ros.org/schema/package_format3.xsd>" schematypens="[http://www.w3.org/2001/XMLSchema"?>\&#x3C;package](http://www.w3.org/2001/XMLSchema"?>\&#x3C;package) format="3">  \<name>py\_pubsub\</name>  \<version>0.0.0\</version>  \<description>Examples of minimal publisher /subscriber using rclpy\</description>  \<maintainer email="<mrthinks@gmail.com>">mrthink\</maintainer>  \<license>Apache License 2.0\</license><br>  \<buildtool\_depend>ament\_python\</buildtool\_depend><br>  \<test\_depend>ament\_copyright\</test\_depend>  \<test\_depend>ament\_flake8\</test\_depend>  \<test\_depend>ament\_pep257\</test\_depend>  \<test\_depend>python3-pytest\</test\_depend><br>  \<export>    \<build\_type>ament\_python\</build\_type>    \<exec\_depend>rclpy\</exec\_depend>    \<exec\_depend>std\_msgs\</exec\_depend>  \</export>\</package></p> |

수정 사항중 dependency부부은 python code에서 import하는 python package를 추가하면 된다.

|                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Column 1                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| <p>from setuptools import setup<br>package\_name = 'py\_pubsub'<br>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='mrthink',    maintainer\_email='<mrthinks@gmail.com>',    description='Examples of minimal publisher/subscriber using rclpy',    license='Apache License 2.0',    tests\_require=\['pytest'],    entry\_points={        'console\_scripts': \[           'talker = py\_pubsub.publisher\_member\_function:main',            'listener = py\_pubsub.subscriber\_member\_function:main',        ],    },)<br></p> |

|          |
| -------- |
| Column 1 |
|          |

setup.cfg는 수정없이 사용. setuptool에게 생성한 실행결과물이 lib 디렉토리에 있다고 알려줌.\
새로운 package build를 하자.$ colcon build --packages-select py\_pubsub\
이제 두 node의 동작을 확인하자.$ . install/setup.bash$ ros2 run py\_pubsub talker\
$ . install/setup.bash$ ros2 run py\_pubsub listener<br>

## + Writing a simple publisher and subscriber (C++)

\
전체 흐름은 python과 동일함.\
$ ros2 pkg create --build-type ament\_cmake cpp\_pubsub\
\
$ wget -O publisher\_member\_function.cpp <https://raw.githubusercontent.com/ros2/examples/master/rclcpp/minimal_publisher/member_function.cpp>\
\
$ wget -O subscriber\_member\_function.cpp <https://raw.githubusercontent.com/ros2/examples/master/rclcpp/minimal_subscriber/member_function.cpp>\
$ tree.├── CMakeLists.txt├── include│   └── cpp\_pubsub├── package.xml└── src    ├── publisher\_member\_function.cpp    └── subscriber\_member\_function.cpp\
<https://github.com/ros2/rclcpp>: rclcpp provides the standard C++ API for interacting with ROS 2.<br>

|                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Column 1                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| #include \<chrono>#include \<memory>#include "rclcpp/rclcpp.hpp"#include "std\_msgs/msg/string.hpp"using namespace std::chrono\_literals;/\* This example creates a subclass of Node and uses std::bind() to register a \* member function as a callback from the timer. \*/class MinimalPublisher : public rclcpp::Node{public:  MinimalPublisher()  : Node("minimal\_publisher"), count\_(0) **=> count\_를 0으로 초기화**  {    publisher\_ = this->create\_publisher\<std\_msgs::msg::String>("topic", 10);   **=> Message type으로 String을 사용하고 topic 이름을 "topic"으로 정하고 queue 크기를 10으로 설정함.**    timer\_ = this->create\_wall\_timer(      500ms, std::bind(\&MinimalPublisher::timer\_callback, this));    **=> 0.5초마다 callback 함수를 호출하도록 설정함.**  }private:  void timer\_callback()  {    auto message = std\_msgs::msg::String();    message.data = "Hello, world! " + std::to\_string(count\_++);    **=> message 생성.**    RCLCPP\_INFO(this->get\_logger(), "Publishing: '%s'", message.data.c\_str());    **=> console에 내용 출력.**    publisher\_->publish(message);    **=> Message 발송.**  }  rclcpp::TimerBase::SharedPtr timer\_;  rclcpp::Publisher\<std\_msgs::msg::String>::SharedPtr publisher\_;  size\_t count\_;};int main(int argc, char \* argv\[]){  rclcpp::init(argc, argv);  rclcpp::spin(std::make\_shared\<MinimalPublisher>());  rclcpp::shutdown();  return 0;} |

|                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Column 1                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
| #include \<memory> #include "rclcpp/rclcpp.hpp" #include "std\_msgs/msg/string.hpp" using std::placeholders::\_1; class MinimalSubscriber : public rclcpp::Node { public: MinimalSubscriber() : Node("minimal\_subscriber") { subscription\_ = this->create\_subscription\<std\_msgs::msg::String>( "topic", 10, std::bind(\&MinimalSubscriber::topic\_callback, this, \_1)); } private: void topic\_callback(const std\_msgs::msg::String::SharedPtr msg) const { RCLCPP\_INFO(this->get\_logger(), "I heard: '%s'", msg->data.c\_str()); } rclcpp::Subscription\<std\_msgs::msg::String>::SharedPtr subscription\_; }; int main(int argc, char \* argv\[]) { rclcpp::init(argc, argv); rclcpp::spin(std::make\_shared\<MinimalSubscriber>()); rclcpp::shutdown(); return 0; } |

|                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Column 1                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| <p>\<?xml version="1.0"?>\<?xml-model href="<http://download.ros.org/schema/package_format3.xsd>" schematypens="[http://www.w3.org/2001/XMLSchema"?>\&#x3C;package](http://www.w3.org/2001/XMLSchema"?>\&#x3C;package) format="3">  \<name>my\_package2\</name>  \<version>0.0.0\</version>  \<description>Beginner developer tutorials practice package\</description>  \<maintainer email="<mrthinks@gmail.com>">mrthink\</maintainer>  \<license>Apache License 2.0\</license>  \<buildtool\_depend>ament\_cmake\</buildtool\_depend>  \<test\_depend>ament\_lint\_auto\</test\_depend>  \<test\_depend>ament\_lint\_common\</test\_depend>  \<export>    \<build\_type>ament\_cmake\</build\_type>    \<exec\_depend>rclcpp\</exec\_depend>    \<exec\_depend>std\_msgs\</exec\_depend>  \</export>\</package><br></p> |

|                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Column 1                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| <p>cmake\_minimum\_required(VERSION 3.5)project(cpp\_pubsub)# Default to C99if(NOT CMAKE\_C\_STANDARD)  set(CMAKE\_C\_STANDARD 99)endif()# Default to C++14if(NOT CMAKE\_CXX\_STANDARD)  set(CMAKE\_CXX\_STANDARD 14)endif()if(CMAKE\_COMPILER\_IS\_GNUCXX OR CMAKE\_CXX\_COMPILER\_ID MATCHES "Clang")  add\_compile\_options(-Wall -Wextra -Wpedantic)endif()# find dependenciesfind\_package(ament\_cmake REQUIRED)find\_package(rclcpp REQUIRED)find\_package(std\_msgs REQUIRED)# uncomment the following section in order to fill in# further dependencies manually.# find\_package(\<dependency> REQUIRED)add\_executable(talker src/publisher\_member\_function.cpp)ament\_target\_dependencies(talker rclcpp std\_msgs)add\_executable(listener src/subscriber\_member\_function.cpp)ament\_target\_dependencies(listener rclcpp std\_msgs)install(TARGETS  talker  listener  DESTINATION lib/${PROJECT\_NAME})if(BUILD\_TESTING)  find\_package(ament\_lint\_auto REQUIRED)  # the following line skips the linter which checks for copyrights  # uncomment the line when a copyright and license is not present in all source files  #set(ament\_cmake\_copyright\_FOUND TRUE)  # the following line skips cpplint (only works in a git repo)  # uncomment the line when this package is not in a git repo  #set(ament\_cmake\_cpplint\_FOUND TRUE)  ament\_lint\_auto\_find\_test\_dependencies()endif()ament\_package()<br></p> |

\
$ sudo rosdep install -i --from-path src --rosdistro dashing -y\
$ colcon build --packages-select cpp\_pubsub\
$ . install/setup.bash$ ros2 run cpp\_pubsub listener\
$ . install/setup.bash$ ros2 run cpp\_pubsub talker\
ls<br>

## + 미션

\
mimic을 수정하여 입력을 반전시켜 동작하게 하고, 이를 lunch file로 구성하여 turtle sim 동작으로 보자.\* 출력창은 1개만 뜨게 할 것.\
\
정하정<https://github.com/jung-ha-jung/ROS2/tree/master/turtlesim_invert_launch>turtle\_teleop\_key node를 launch 파일에서 실행했더니 키보드 입력시 문자열로 추가되네요.ㅠㅠ![image.png](https://coda.io/contentProxy/w_N8GLWiAl/blobs/bl-SPuAPifU7f/3108539d63d9e7dc9efec8bba1f307c45cf6554df4fa0236d80aa7eb3dc832fb9b776b26bd0a5c1708b64f5f67e3c40347f074ec73dd98642767bb96041365a45cf5b7e9d41737f9d055cb873cd0913bb33ea8c882cf67ed99259527b4f4f3b00910f9a9) ![image.png](https://coda.io/contentProxy/w_N8GLWiAl/blobs/bl-hCnf1CpGrt/b2f12a67d3c96a7b119fbb08b5f43b47caaa0cbca82a53ce630cf96acd477f20feafe666f641dfa4b9f10489a72cc01d3e7c25864f2f0cca42b3d92c35cab12644f9613e643a4a0934270a2a482b880c4f0c92e0c4f8be8f6e9551ea5065205f8d60edc9).<br>
