# 3장 ROS 구조 및 빌드 시스템

### 1. ROS 용어

* 패키지 : ROS 소프트웨어의 기본 단위. 패키지는 노드, 라이브러리, 환경설정 파일들을 통합하는 최소의 빌드 단위이며, 배포 단위이다.
* 패키지 매니페스트 : 패키지의 작성자, 라이선스, 의존성, 컨피그레이션 플레그 등을 포함하는 패키지 정보
* 메타 패키지 : 이전에는 스택으로 불리웠지만, 특수한 목적을 위한 패키지 그룹을 지칭한다. 대표적인 예로 네비게이션 스택을 예로 들 수 있다.
* 메시지 : 한 ROS 프로세서에서 다른 ROS 프로세서로 정보를 전달하는 한 형태

![image.png](https://coda.io/contentProxy/oXCJn1awF2/blobs/bl-DMBXpEHRzz/0a7779b671b249ae0488b6a0f06fedd9d661c0205cb6b7706ddd69535904b0f35728babb602a9e00f32dda6084ff853fd2b200aafd368eabf2f14f8b9935040f66311be1ddccf08c22a626085f79d687ecdaf93c5adf42947b6267e88bee5169401f436d)

* 서비스 : 프로세스간의 요청/응답 상호작용
* Service, Service Server, Service Client

![image.png](https://coda.io/contentProxy/oXCJn1awF2/blobs/bl-42xSFDZjS4/6d9efc8777cce7fce8ab9185f93a55644e34c4ba2e86ad5613261e0c4511cac6b86fe4bbefe3d09821032060ca12083f62ac371acb90fdc861d39db3f7be94a1967aa13493633ad6358430a198182e4ec0793f7da9142f0368c622cd696f289f202ea3f7)

* Node : 최소 단위의 실행 가능한 프로세서를 가리키는 용어로써 하나의 실행 가능한 프로그램으로 생각하면 된다. ROS에서는 최소한의 실행 단위로 프로그램을 나누어 작업하게 된다. 각 노드는 메시지 통신으로 데이터를 주고 받는다.
* Package : 하나 이상의 노드, 노드 실행을 위한 정보 등을 묶어 놓은것. 또한, 패키지의 묶음을  메타패키지라 하여 따로 분리 한다.
* Message : 메시지를 통해 노드 간의 데이터를 주고 받게 된다. 메시지는 integer, floating point, boolean와 같은 변수 형태이다. 또한, 메시지 안에 메시지를 품고 있는 간단한 데이터 구조 및 메시지들의 배열과 같은 구조도 사용할 수 있다.
* Publisher, Subscriber, Topic

![](https://917233451-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LcW4PzQzrJVLjrT8lUh%2F-MNBQpKGmXCfslqzaQMe%2F-MNC6_ftU4n-qqFNp1ic%2FConceptual-model-of-ROS-topics-presented-by-Radu-Rusu-in-his-tutorial8.png?alt=media\&token=a0de4716-9958-4d74-947c-120c78f88507)

* Action, Action Server, Action Client

![image.png](https://coda.io/contentProxy/oXCJn1awF2/blobs/bl-1Jtr7XV5Lf/64c152c99865c9375c806ccfd21bffd9df8ebc861047b37072ac63cf77e2e39c7520450cb64b07da1188a29e78dc572366951506004e1ab84e6f9c24c511fd1bb3ec1ab56b83d056c9749c529c790e292f0aa7cb1029a9ad6fbafdcc743f0eb2c73ffad2)

### 2. ROS 통신 방식

![image.png](https://coda.io/contentProxy/oXCJn1awF2/blobs/bl-oCeYSrEjnZ/dbabe085ea022d9882d4d63d9a866641eb023bab202275b25198151d4b8cbb5cb4e605c8ac0aa3e173c44fd288da4bb28a155ff17e60cbece9664f77c2dc9ade078a464577ae2835bae82546665f9d977d9ced2842b3064d7dd15d4fcf48dab613c7ca57)

\ <br>

![image.png](https://coda.io/contentProxy/oXCJn1awF2/blobs/bl-h61bWf86AK/9e04beefe5043b0803395137b8f889ca48859466d9371628150687f1a85ee513b04d305f465b673a0c6d05c8b5784e6b7acbedd93764dc38e326c91c99d2c2a8e8ef3b9f3a369f2f4f7cbe4ab069977b8f2723ec2d16de0ef5d1dfa8707cd7e207297c5f)

### 3. TF(Transform)

* 각조인트(joint)들의 상대좌표 변환
* 트리(tree) 형태로 조인트들 간의 관계도를 표시함

![image.png](https://coda.io/contentProxy/oXCJn1awF2/blobs/bl-1IjoerM6_D/c9feb20391fc83454f31deb9a5e6ee40d95e5123c12cd9b131d6eb5e3b8f0f03bda3098c96167f99a4b90fcaca4ac26a711d3ed75aba818151843f3ff4c5c093775779a043669cf6b121d2e4c31e73e1ff41c754f8d10bd85ea37ef84a1bd9673c9e324f)

### 4. ROS 관련 명령어

|       |     |                           |                       |
| ----- | --- | ------------------------- | --------------------- |
| 명령어   | 중요도 | 명령어풀이                     | 세부설명                  |
| roscd | ★★★ | ros+cd(changes directory) | 지정한 ROS 패키지의 디렉터리로 이동 |
| rosls | ★☆☆ | ros+ls(lists files)       | ROS 패키지의 파일목록 확인      |
| rosed | ★☆☆ | ros+ed(editor)            | ROS 패키지의 파일편집         |
| roscp | ★☆☆ | ros+cp(copies files)      | ROS 패키지의 파일복사         |
| rospd | ☆☆☆ | ros+pushd                 | ROS 디렉터리 인덱스에 디렉터리 추가 |
| rosd  | ☆☆☆ | ros+directory             | ROS 디렉터리 인덱스 확인       |

|           |     |            |                                                            |
| --------- | --- | ---------- | ---------------------------------------------------------- |
| 명령어       | 중요도 | 명령어풀이      | 세부설명                                                       |
| roscore   | ★★★ | ros+core   | -master(ROS 네임서비스) -rosout(로그기록) -parameter server(파라미터관리) |
| rosrun    | ★★★ | ros+run    | 노드실행                                                       |
| roslaunch | ★★★ | ros+launch | 노드를 여러개 실행 및 실행 옵션 설정                                      |
| rosclean  | ★★☆ | ros+clean  | ROS 로그 파일을 검사하거나 삭제                                        |

|            |     |                      |                           |
| ---------- | --- | -------------------- | ------------------------- |
| 명령어        | 중요도 | 명령어풀이                | 세부설명                      |
| rostopic   | ★★★ | ros+topic            | ROS 토픽 정보 확인              |
| rosservice | ★★★ | ros+service          | ROS 서비스 정보 확인             |
| rosnode    | ★★★ | ros+node             | ROS 노드 정보 확인              |
| rosparam   | ★★★ | ros+param(parameter) | ROS 파라미터 정보 확인, 수정        |
| rosbag     | ★★★ | ros+bag              | ROS 메시지 기록, 재생            |
| rosmsg     | ★★☆ | ros+msg              | ROS 메시지 정보 확인             |
| rossrv     | ★★☆ | ros+srv              | ROS 서비스 정보 확인             |
| rosversion | ★☆☆ | ros+version          | ROS 패키지 및 배포 릴리즈 버전 정보 확인 |
| roswtf     | ☆☆☆ | ros+wtf              | ROS 시스템 검사                |

|                             |     |                                          |
| --------------------------- | --- | ---------------------------------------- |
| 명령어                         | 중요도 | 세부설명                                     |
| catkin\_create\_pkg         | ★★★ | 패키지 자동 생성                                |
| catkin\_make                | ★★★ | 캐킨 빌드시스템에 기반을 둔 빌드                       |
| catkin\_eclipse             | ★★☆ | 캐킨 빌드 시스템으로 생성한 패키지를 이클립스에서 사용 할 수 있게 변경 |
| catkin\_prepare\_release    | ★★☆ | 릴리즈 할때 사용되는 로그정리 및 버전 태깅                 |
| catkin\_generate\_changelog | ★★☆ | 릴리즈 할때 CHANGELOG.rst 파일 생성 또는 업데이트       |
| catkin\_init\_workspace     | ★★☆ | 캐킨 빌드 시스템의 작업폴더 초기화                      |
| catkin\_find                | ★☆☆ | 캐킨 검색                                    |

|               |     |                    |                                 |
| ------------- | --- | ------------------ | ------------------------------- |
| 명령어           | 중요도 | 명령어풀이              | 세부설명                            |
| rospack       | ★★★ | ros+pack(age)      | ROS 패키지와 관련된 정보 보기              |
| rosinstall    | ★★☆ | ros+install        | ROS 추가 패키지 설치                   |
| rosdep        | ★★☆ | ros+dep(endencies) | 해당패키지의 의존성 파일 설치                |
| roslocate     | ☆☆☆ | ros+locate         | ROS 패키지 정보 관련 명령어               |
| roscreate-pkg | ☆☆☆ | ros+create-pkg     | ROS 패키지 자동생성(구rosbuild 시스템에서사용) |
| rosmake       | ☆☆☆ | ros+make           | ROS 패키지를 빌드(구rosbuild 시스템에서사용)  |

### 5. 빌드 시스템

|             |          |
| ----------- | -------- |
| Column 1    | Column 2 |
| Quantity    | Unit     |
| angle       | radian   |
| frequency   | hertz    |
| force       | newton   |
| power       | watt     |
| voltage     | volt     |
| length      | meter    |
| mess        | kilogram |
| time        | second   |
| current     | ampere   |
| temperature | celsius  |

|         |               |                                               |
| ------- | ------------- | --------------------------------------------- |
| 대상      | 명명규칙          | 예제                                            |
| 패키지     | under\_scored | Ex) first\_ros\_package                       |
| 토픽, 서비스 | under\_scored | Ex) raw\_image                                |
| 파일      | under\_scored | Ex) turtlebot3\_fake.cpp                      |
| 네임스페이스  | under\_scored | Ex) ros\_awesome\_package                     |
| 변수      | under\_scored | Ex) string table\_name;                       |
| 타입      | CamelCased    | Ex) typedefint32\_t propertiesNumber;         |
| 클래스     | CamelCased    | Ex) classUrlTable                             |
| 구조체     | CamelCased    | Ex) structUrlTableProperties                  |
| 열거형     | CamelCased    | Ex) enumChoiceNumber                          |
| 함수      | camelCased    | Ex) addTableEntry();                          |
| 메소드     | camelCased    | Ex) void setNumEntries(int32\_t num\_entries) |
| 상수      | ALL\_CAPITALS | Ex) const uint8\_t DAYS\_IN\_A\_WEEK = 7;     |

\
\
SI(Systeme Internationale) 단위 사용\ <br>

![image.png](https://coda.io/contentProxy/oXCJn1awF2/blobs/bl-9n5KCYjUCZ/4a5bd0013714cef7bb232c5984c09031a25c01144449a5f5418f6f2256a1b72b83e496b982ce903dce5a99c52e99dc74296e02eb5dcb514e85181bd01b24290fa58ff4f3a013f27fcbe5884806ea7fe29c064df882e93d49384703e59dfcfcb404dc9cb6)

### **5.1 Topic / Publisher / Subscriber 실습**

**1) 패키지 생성**

```
cd ~/catkin_ws/src
```

```
catkin_create_pkg ros_tutorials_topic message_generation std_msgs roscpp
```

```
cd ros_tutorials_topic
```

```
ls
```

```
include → 헤더파일폴더
src→ 소스코드폴더
CMakeLists.txt → 빌드설정파일
package.xml→ 패키지설정파일
```

\
**2) 패키지 설정 파일(package.xml) 수정**

```
gedit package.xml
```

```
<?xmlversion="1.0"?>
<packageformat="2">
<name>ros_tutorials_topic</name>
<version>0.1.0</version>
<description>ROS turtorialpackage to learn the topic</description>
<license>Apache 2.0</license>
<authoremail="pyo@robotis.com">Yoonseok Pyo</author>
<maintaineremail="pyo@robotis.com">Yoonseok Pyo</maintainer>
<urltype="website">http://www.robotis.com</url>
<urltype="repository">https://github.com/ROBOTIS-GIT/ros_tutorials.git</url>
<urltype="bugtracker">https://github.com/ROBOTIS-GIT/ros_tutorials/issues</url>
<buildtool_depend>catkin</buildtool_depend>
<depend>roscpp</depend>
<depend>std_msgs</depend>
<depend>message_generation</depend>
<export></export >
</package> 
```

\
**3) 빌드 설정 파일(CMakeLists.txt) 수정**

```
gedit CMakeLists.txt
```

```
cmake_minimum_required(VERSION 2.8.3) 
project(ros_tutorials_topic) 
## 캐킨빌드를할때요구되는구성요소패키지이다.
## 의존성패키지로message_generation, std_msgs, roscpp이며이패키지들이존재하지않으면빌드도중에에러가난다.
find_package(catkin REQUIRED COMPONENTS message_generationstd_msgsroscpp)
## 메시지선언: MsgTutorial.msg 
add_message_files(FILES MsgTutorial.msg)
## 의존하는메시지를설정하는옵션이다.
## std_msgs가설치되어있지않다면빌드도중에에러가난다.
generate_messages(DEPENDENCIES std_msgs)
## 캐킨패키지옵션으로라이브러리, 캐킨빌드의존성, 시스템의존패키지를기술한다. 
catkin_package( 
LIBRARIES ros_tutorials_topic
CATKIN_DEPENDS std_msgsroscpp
)

## 인클루드디렉터리를설정한다.
include_directories(${catkin_INCLUDE_DIRS})
## topic_publisher노드에대한빌드옵션이다. 
## 실행파일, 타깃링크라이브러리, 추가의존성등을설정한다.
add_executable(topic_publisher src/topic_publisher.cpp)
add_dependencies(topic_publisher ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
target_link_libraries(topic_publisher ${catkin_LIBRARIES})
## topic_subscriber노드에대한빌드옵션이다. 
add_executable(topic_subscriber src/topic_subscriber.cpp)
add_dependencies(topic_subscriber ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
target_link_libraries(topic_subscriber ${catkin_LIBRARIES})
```

\
**4) 메시지 파일 작성**

```
roscd ros_tutorials_topic
```

```
mkdir msg
```

```
cd msg
```

```
gedit MsgTutorial.msg
```

```
time stamp
int32 data
```

\
**5) 퍼블리셔 노드 작성**

```
roscd ros_tutorials_topic/src
```

```
gedit topic_publisher.cpp
```

```
#include "ros/ros.h"// ROS 기본 헤더 파일
#include "ros_tutorials_topic/MsgTutorial.h"// MsgTutorial 메시지 파일 헤더(빌드 후 자동 생성 됨)
int main(int argc, char **argv) // 노드 메인 함수
{
ros::init(argc, argv, "topic_publisher"); // 노드명 초기화
ros::NodeHandle nh;// ROS 시스템과 통신을 위한 노드 핸들 선언
// 퍼블리셔선언, ros_tutorials_topic패키지의MsgTutorial메시지파일을이용한
// 퍼블리셔ros_tutorial_pub를작성한다. 토픽명은"ros_tutorial_msg" 이며,
// 퍼블리셔큐(queue) 사이즈를100개로설정한다는것이다
ros::Publisher ros_tutorial_pub= nh.advertise<ros_tutorials_topic::MsgTutorial>("ros_tutorial_msg", 100);
// 루프주기를설정한다. "10" 이라는것은10Hz를말하는것으로0.1초간격으로반복된다
ros::Rate loop_rate(10);
// MsgTutorial메시지파일형식으로msg라는메시지를선언
ros_tutorials_topic::MsgTutorial msg;
// 메시지에사용될변수선언

int count = 0;

while (ros::ok())
{
msg.stamp= ros::Time::now();// 현재시간을msg의하위stamp 메시지에담는다
msg.data= count; // count라는변수값을msg의하위data 메시지에담는다
ROS_INFO("send msg= %d", msg.stamp.sec); // stamp.sec메시지를표시한다
ROS_INFO("send msg= %d", msg.stamp.nsec); // stamp.nsec메시지를표시한다
ROS_INFO("send msg= %d", msg.data); // data 메시지를표시한다
ros_tutorial_pub.publish(msg);// 메시지를발행한다
loop_rate.sleep();// 위에서정한루프주기에따라슬립에들어간다
++count;// count 변수1씩증가
}

return 0;
}
```

\
**6) 서브 스크라이버 노드 작성**<br>

```
roscd ros_tutorials_topic/src→ 패키지의 소스 폴더인 src폴더로 이동
```

```
gedit topic_subscriber.cpp→ 소스파일 신규작성 및 내용 수정
```

```
#include "ros/ros.h" // ROS 기본헤더파일
#include "ros_tutorials_topic/MsgTutorial.h" // MsgTutorial메시지파일헤더(빌드후자동생성됨)
// 메시지콜백함수로써, 밑에서설정한ros_tutorial_msg라는이름의토픽
// 메시지를수신하였을때동작하는함수이다
// 입력메시지로는ros_tutorials_topic패키지의MsgTutorial메시지를받도록되어있다

void msgCallback(const ros_tutorials_topic::MsgTutorial::ConstPtr& msg)
{
ROS_INFO("recievemsg= %d", msg->stamp.sec); // stamp.sec메시지를표시한다
ROS_INFO("recievemsg= %d", msg->stamp.nsec); // stamp.nsec메시지를표시한다
ROS_INFO("recievemsg= %d", msg->data); // data 메시지를표시한다
}

int main(int argc, char **argv)// 노드메인함수
{
ros::init(argc, argv, "topic_subscriber");// 노드명초기화
ros::NodeHandle nh; // ROS 시스템과통신을위한노드핸들선언
// 서브스크라이버선언, ros_tutorials_topic패키지의MsgTutorial메시지파일을이용한
// 서브스크라이버ros_tutorial_sub를작성한다. 토픽명은"ros_tutorial_msg" 이며,
// 서브스크라이버큐(queue) 사이즈를100개로설정한다는것이다
ros::Subscriber ros_tutorial_sub= nh.subscribe("ros_tutorial_msg", 100, msgCallback);
// 콜백함수호출을위한함수로써, 메시지가수신되기를대기, 
// 수신되었을경우콜백함수를실행한다
ros::spin();

return 0;
}
```

\
**7) ROS 노드 빌드**

```
cd~/catkin_ws
```

```
catkin_make
```

\
\&#xNAN;**•ros\_tutorials\_topic 패키지의 소스 코드 파일: \~/catkin\_ws/src/ros\_tutorials\_topic/src**

**•ros\_tutorials\_topic패키지의 메시지 파일: \~/catkin\_ws/src/ros\_tutorials\_topic/msg**

**•빌드된 결과물은 /catkin\_ws의 /build와/devel폴더에 각각 생성**

**•/build 폴더에는 캐킨 빌드에서 사용된 설정 내용이 저장**

**•/devel/lib/ros\_tutorials\_topic폴더에는 실행 파일이 저장**

**•/devel/include/ros\_tutorials\_topic폴더에는 메시지 파일로 부터 자동 생성된 메시지 헤더 파일이 저장**<br>

```
roscore
```

```
rosrun ros_tutorials_topic topic_publisher
```

```
rostopic list
```

```
/ros_tutorial_msg
/rosout
/rosout_agg
```

```
rostopic echo /ros_tutorial_msg
```

```
rosrun ros_tutorials_topic topic_subscriber
```

```
rqt_graph
```

![image.png](https://coda.io/contentProxy/oXCJn1awF2/blobs/bl-mSnsPJRh-h/d2927bca138467059c54359743842b88f46de591aa877cbb460471522816090dc9b77c042c24349bb466a25edd589ed9f907c91b2a221ddec9dc50a0a0b896f98728c6a4629f0211e352c9a632f3f022c75b4aefa2796af183e123f30f557ffb44d57ad9)

### **5.2 git을 활용하여 예제 활용하기**

```
sudo apt-get install git
```

```
cd~/catkin_ws/src
```

```
git clone https://github.com/ROBOTIS-GIT/ros_tutorials.git
```

```
cd~/catkin_ws
```

```
catkin_make
```

```
rosrun ros_tutorials_topic topic_publisher
```

```
rosrun ros_tutorials_topic topic_subscriber
```

### &#x20; 5.3 roslaunch

\
~~`•roslaunch는 하나 이상의 정해진 노드를 실행 시킬수 있다.`~~

~~`•roslaunch는‘*.launch’라는 파일을 사용하여 실행노드를 설정하는데 이는XML 기반이며, 태그별 옵션을 제공한다.`~~

~~`•실행 명령어는"roslaunch [패키지명] [roslaunch파일]”이다.`~~<br>

```
roscd ros_tutorials_topic
```

```
mkdir launch
```

```
cd launch
```

```
gedit union.launch
```

```
<launch>
<node pkg="ros_tutorials_topic" type="topic_publisher" name="topic_publisher1"/>
<node pkg="ros_tutorials_topic" type="topic_subscriber" name="topic_subscriber1"/>
<node pkg="ros_tutorials_topic" type="topic_publisher" name="topic_publisher2"/>
<node pkg="ros_tutorials_topic" type="topic_subscriber" name="topic_subscriber2"/>
</launch> 
```

```
•pkg 패키지의 이름
•type 실제 실행 할 노드의 이름(노드명)
•name 위 type에 해당하는 노드가 실행될때 붙여지는 이름(실행명), 일반적으로는 type과 같게 설정하지만 필요에 따라 실행할때 이름을 변경하도록설정할수 있다. 
```

```
roslaunch ros_tutorials_topic union.launch --screen
```

```
rosnode list
```

```
/topic_publisher1
/topic_publisher2
/topic_subscriber1
/topic_subscriber2
/rosout
```

```
rqt_graph
```

\ <br>

![image.png](https://coda.io/contentProxy/oXCJn1awF2/blobs/bl-nrdTWrdwA0/baca5091259499249e92a4c40caa59a72f4f20620bd4752ccef5e0668cffa844e7aa9ae237334583ba7e41925e967ef3fdc2e014ed5074a0534b9c60c44ea7572005a60b9369f0a5df0a51cbd8e37350fde0c36b72727c408a543175514a07a1136ea988)
