💻 Computer Science/ROS

[ROS] 간단한 publisher와 subscriber (topic tutorial)

bigbigpark 2021. 1. 31. 13:58

 

[블로그 이전 관련!!]

더나은 환경에서 양질의 게시글을 제공하기 위해 블로그를 옮겼습니다

아래쪽 주소로 들어가지면 게시글을 새로 정리해놓았습니다!

https://bigbigpark.github.io/ros/rospy-tutorial/

 

 

 

 

 

 

 

안녕하세요~ 오늘은 ros tutorial 중 기본 중의 기본인

ros publisher와 ros subscriber을 작성해보겠습니다!

또한 custom 메세지를 빌드하고 추가하는 방법도 알아보겠습니다

 

 

전체 코드는 본문 제일 하단에 첨부하겠습니다

 

 

전체적인 컨셉

 

- catkin_create_pkg를 이용하여 프로젝트 빌드

- publisher와 subscriber를 하나씩 작성

- TestMsg.msg라는 메세지 파일을 생성하고 헤더파일로 불러오기

 

 

$catkin_create_pkg tistory_tutorial roscpp std_msgs message_generation

 

 

// 설명

- tistory_tutorial 프로젝트에 roscpp, std_msgs, message_generation이라는 종속 패키지를 추가하겠다

 

 

$touch msg_pub.cpp msg_sub.cpp [경로 주의]

 

 

{프로젝트 경로}/src에서

msg_pub.cpp

msg_sub.cpp

라는 두 개의 cpp파일 생성

 

 

msg_pub.cpp , msg_sub.cpp 코드 스켈레톤 작성

 

- 스켈레톤이 해골 뼈다구잖아요?

- 그래서 코드 스켈레톤(=code skeleton)하면 코드 뼈대랑 같은 말입니다

 

msg_pub.cpp
msg_sub.cpp

 

★ 메세지 정의 ★

 

 

// 프로젝트 안에 msg폴더를 생성하고 그 안에 TestMsg.msg를 생성하는 과정입니다 

$roscd tistory_tutorial
$mkdir msg
$cd msg
$gedit TestMsg.msg

 

메세지 폴더 안에서는

float64 x

float64 y

float64 z

해서 저장(Ctrl+S) 해주세요!!

 

 

package.xml 수정

 

 

57번과 60번 줄을 추가해주세요!

 

 

CMakeLists.txt 수정

 

 

위의 사진과 같이 추가해주시면 됩니다~!

간단하게 설명하자면 

add_message_files는 프로젝트 안 'msg'폴더 안에 있는 메세지 파일을 생성하겠다는 뜻이에요

generate_messages는 추가된 메세지나 서비스에 밑에 나열된 종속패키지를 추가한다는 말입니다

 

 

$catkin_make

 

 

catkin_make로 빌드를 해줍니다

이 경우 TestMsg.msg 파일이 TestMsgs.h파일로 알아서 만들어집니다 ㅎㅎ

따라서 저희가 할 거는 cpp파일에서 헤더파일을 include 하는 작업만 남아있습니다!

 

 

cpp파일에서 헤더파일 추가

 

 

#include <프로젝트_이름/메세지_이름.h>

순으로 선언해주시면 됩니다

이제 본격적인 publishersubscriber를 만들어봅시다!!

 

 

msg_pub.cpp

 

 

주석 단다고 달았는데

질문 있으시면 댓글 남겨주세요~ ㅎㅎ

밑에 subscribe도 첨부했습니다

 

 

msg_sub.cpp

 

 

자 이제 모든 준비가 끝났습니다

msg_pub.cpp와 msg_sub.cpp파일 작성이 끝났으니

이제 실행가능한 형태(=노드)로 설정해주는 작업만 남았네요

 

 

CMakeLists.txt에서 파일 실행가능하도록 변경

 

 

- CMakeLists.txt 에서 아래쪽으로 좀 스크롤을 내려보시면 이와 비슷한 코드가 주석처리가 되어 있는데

아무데나 이렇게 넣어주시면 됩니다!

 

간단하게 설명을 드리자면,

add_executable(msg_pub src/msg_pub.cpp)

add_executable(실행할 때 사용할 노드명 src/실제 코드) 입니다

 

add_dependencies(msg_pub ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})

target_link_libraries(msg_pub ${catkin_LIBRARIES})

비슷하게 위의 두 명령어 제일 앞부분에 실행할 때 사용할 노드명(ex. msg_pub) 을 적어주시면 됩니다

 

마지막으로 catkin_make를 해줄게요~!

 

 

 

결과

 

 

 

 

전체 코드

msg_pub.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
#include <ros/ros.h>
#include <tistory_tutorial/TestMsg.h>
 
int main(int argc, char** argv)
{
    // ros node 초기화
    ros::init(argc, argv, "msg_pub_node");
    ros::NodeHandle nh;
 
    // loop_rate를 1 Hz로 설정 
    ros::Rate r(1);
 
    // "chat"이라는 이름의 토픽을 publish 하고, 큐(queue)의 크기는 1로 설정
    ros::Publisher pub = nh.advertise<tistory_tutorial::TestMsg>("chat"1);
    tistory_tutorial::TestMsg msg;
 
    while(ros::ok())
    {
        msg.x = 10;
        msg.y = 100;
        msg.z = 1000;
 
        pub.publish(msg);
        r.sleep();
    }
 
    return 0;
}
cs

 

msg_sub.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
 
#include <ros/ros.h>
#include <tistory_tutorial/TestMsg.h>
 
void msgcallBack(const tistory_tutorial::TestMsg::ConstPtr& msg)
{
    ROS_INFO("x : %f", msg->x);
    ROS_INFO("y : %f", msg->y);
    ROS_INFO("z : %f", msg->z);
}
 
int main(int argc, char** argv)
{
    // ros node 초기화
    ros::init(argc, argv, "msg_sub_node");
    ros::NodeHandle nh;
 
    // loop_rate를 1 Hz = 1초로 설정
    ros::Rate r(1);
 
    // "chat"이라는 이름의 토픽을 publish 하고, 큐(queue)의 크기는 1로 설정
    ros::Subscriber sub = nh.subscribe<tistory_tutorial::TestMsg>("chat"1, msgcallBack);
    tistory_tutorial::TestMsg msg;
 
    while(ros::ok())
    {
        ros::spinOnce();
        
        r.sleep();
    }
 
    return 0;
}
 
 
cs