본문 바로가기
IT 프로그래밍 관련/ROS

ROS 패키지 생성하기(Publisher, Subscriber, Topic사용)

by 지나는행인 2021. 6. 8.
728x90

한번 기본적인 패키지를 생성해보려고 한다. 

 

Topic 메세지를 이용한 Publisher , Subscriber 노드의 패키지이다.

 

ROS는 C++ , python 을 주로 활용하여 코드를 작성하는데 ,

 

C++의 활용도가 조금 더 높다고 한다.

 

먼저 모든것의 선행조건은 해당 디렉토리로의 이동이다.

 

앞서 이야기 했듯이  ROS 패키지는 워크스페이스의 src 디렉토리에서 생성한다.

 

src로 이동 하여 , 패키지를 생성하는  명령어를 실행한다.

 

$ catkin_create_pkg [생성할 패키지 이름] [의존성패키지1 의존성패키지2 ........]

 

* 명령어 실행화면

위 명령에서의 [생성할 패키지이름]은 yh_210608_1 이 되고

 

의존성패키지로는 3개가 포함되는데 ,  std_msgs 와 roscpp , message_generation 이다.

 

std_msgs는 기본 메시지 방식을 사용한다는 것이고,

 

roscpp는 c++ 언어를 이용한다는 것이다.

 

message_generation 은 내가 메시지 까지 작성을 할때만 이용한다.

( 기본 메시지를 이용할때는 사용하지 않는다 )

* 여기서 메시지는 topic , service , action   을 이야기 한다.

 

여기까지 하였다면 src 디렉토리 하위에 패키지이름 (yh_210608_1) 디렉토리가 생성된다.

 

* yh_210608_1 디렉토리

패키지 디렉토리로 이동하여 기본설정, 정보등을 먼저 수정한다.

 

제일 먼저 packge.xml 을 수정하여 본다.

 

package.xml은 이 패키지의 기본 정보이다.

 

$ gedit pakage.xml

 

* pakage.xml 변경 전

기존 그대로의 pakage.xml 파일이다.

 

여기서 수정을 안해도 되지만, 한번 수정해보자.

 

위의 패키지 관련 정보는 내가 만든 패키지 정보이니 name 등 한번 확인하고,

 

<mainainer>  는 유지보안관련자 정보이다.  

 

정보를 수정해보자.

 

중간에 보면 <author> 정보가 있다. 패키지 생성자니까 이것도 수정해본다.

 

그리고 아래로 쭉 내리면

 

<buildtool_depend> 부터 내용이 있다.

 

catkin빌더를 이용하니까 catkin이 입력되어 있고,

 

아까 패키지 생성시 내가 입력한 의존성 패키지 관련하여 적혀있으니 참고한다.

 

*message_generation 은 메세지 생성시 한번만 이용하기 때문에 , build_depend에도 한번만 기재된다.

 

* 변경 후

이제 그 다음으로는 메세지를 작성한다.

 

메세지디렉토리를 만들어야 한다. 이 디렉토리는 내가 만든 패키지 디렉토리인 yh_210608_1 하위에 만든다.

 

메세지의 종류로는 topic , service , action 이 있는데 디렉토리명으로 이용한다.

 

topic 은 메세지의 가장 기본이 되는 종류이기 때문에 , 그냥 메시지의 약자인 msg로 생성한다.

 

service 는 srv , action 은 action 으로 생성한다.

 

여기에서는 가장 기본이 되는 topic으로 생성한다.

 

* msg 디렉토리 생성

생성 후에 msg 디렉토리로 이동하여 하위에 메세지파일을 만들어 준다.

 

확장자는 메세지 파일이라는 뜻으로 .msg로 만든다.

 

$ gedit [메시지파일 이름].msg

 

메시지파일 이름을 yh_msg_1로 만들어 보겠다.

 

만들어서 내용으로 간단하게 ,   시간을 알리는 time과 숫자의 int32 를 형식으로 한 변수 두개를 만들었다.

 

*명령어 실행 화면 및 gedit 파일 화면

이렇게 하면 기본적인 topic 메세지를 생성한 것이 된다.

 

이제 패키지의 기본이 되는 노드를 만든다.

 

topic 메시지를 이용하는 노드는 계속 정보를 발행하는 Publisher  ,

 

원하는 정보를 받아오는 Subscriber가 있다. 이 두개의 노드는 yh_210608_1 하위의 새로 생성된 src 디렉토리 하위에 파일로

 

생성한다.

 

먼저 노드 두개를 생성하고 안의 내용은 각각 수정하는 걸로 하겠다.

 

publisher 노드는 yh_pub_1 로 subscriber 노드는 yh_sub_1 로 생성한다. ( c++로 코드 작성하기 때문에 확장자는 .cpp)

 

* publisher node 생성
* subscriber node 생성

 

두 개의 노드를 만들었으니 이제 publisher node부터 수정해 본다.

 

publisher node는 정보를 계속 보내는 노드이다.

 

c++  형식에 맞게.. ROS 함수 형식에 맞게 작성하여 준다 .

 

코드 예제 (yh_pub_1.cpp)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include "ros/ros.h"  //ROS 기본 헤더파일
#include "yh_210608_1/yh_msg_1.h" //패키지이름 / 메세지파일.h 
 
int main(int argc, char **argv) //c++ 의 기본 함수형태
{
    ros::init(argc, argv, "yh_pub_1"); //노드명 초기화
    ros::NodeHandle nh; //ROS시스템과 통신을 위한 노드핸들 선언
 
 
    ros::Publisher pub = nh.advertise<yh_210608_1::yh_msg_1>("yh_topic_1",100);
    //퍼블리시어 선언, 패키지 ()의 메시지파일()을 이용
     //퍼블리시어()을 작성
    //토픽명은 ()이며 퍼블리시어큐 사이즈를 ()개로 설정한다.
    //publisher이기 때문에 advertise 만듬
    
    ros::Rate loop_rate(2); //루프 주기를 2Hz로 설정 (1초에 2번)
    
    yh_210608_1::yh_msg_1 msg; //내가 만든 메시지 파일 형식으로 ()라는 메세지선언
    
    int count = 0;
 
    while(ros::ok()) //ros 가 활성화되면
    {
        msg.stamp = ros::Time::now(); //현재 시간을 msg 하위 stamp메세지에 담음
        msg.data = count; //count 변수 값을 msg 하위 data 메세지에 담는다.
        ROS_INFO("send msg = %d", msg.stamp.sec);
        ROS_INFO("send msg = %d", msg.stamp.nsec);
        ROS_INFO("send msg = %d", msg.data);
 
        pub.publish(msg);
        loop_rate.sleep();
        ++count;
 
    }
    return 0;
}
cs

 

 

다음은 이 publisher를 받을 subscriber node를 작성한다.

 

코드예제(yh_sub_1.cpp)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include "ros/ros.h"
#include "yh_210608_1/yh_msg_1.h"
 
void msgCallback(const yh_210608_1::yh_msg_1::ConstPtr&msg)  //const 상수
{
    ROS_INFO("receive msg = %d", msg -> stamp.sec);
    ROS_INFO("receive msg = %d", msg -> stamp.nsec);
    ROS_INFO("receive msg = %d", msg -> data);
}
 
int main(int argc, char **argv)
{
    ros::init(argc, argv, "yh_sub_1");
    ros::NodeHandle nh;
    
    ros::Subscriber sub = nh.subscribe("yh_topic_1",100,msgCallback);
    ros::spin(); //어떤 값이 들어오기 전까지 대기 (다시 위로 올라감)
    return 0;
}
cs

 

노드 파일을 다 작성하였으면 , 해당 패키지의 CMakelists.txt 파일을 수정한다.

*명령어 실행

 

주석 부분을 해제해야하고 , 노드 관련하여 수정해야 한다.

아래는 수정 관련이니 , 비교하면서 바꾸면 된다.

 

######## install ####### 관련 부분은 건드리지 않아도 된다.

 

이제 !!!! 패키지는 완성이다 .

 

실행이 잘 되는지 확인하자!

 

먼저 cd ~/catkin_ws && catkin_make   를 실행한다.

 

후에 빌드된 내용을 source devel/setup.bash 명령어로 등록시켜주고,

 

rospack profile  을 실행한다.

 

이제 터미널을 켜고  , roscore 로 마스터를 실행하고 ,

 

다른 터미널로 rosrun yh_210608_1 yh_pub_1         퍼블리셔 노드를 실행하고 정보가 출력되는게 확인 되면

 

다른 터미널로 rosrun yh_210609_1 yh_sub_1  서브스크라이브 노드를 실행하고 정보를 받아오는 것을 확인하자.

 

 

굿!

 

댓글