ROS_Message 실습

지토·2021년 11월 5일
0

경희대학교 황효석 교수님의 2021-2 로봇 프로그래밍 수업을 듣고 요약한 것입니다.

ROS 는 모든 단위가 패키지로 되어 있다. 패키지 안에 노드가 하나라도 들어 있으면 그것은 패키지에 포함되어 있어야 한다. 그렇기 때문에 처음에는 패키지를 만들어주고, 그 패키지 내부에 두 개의 노드에 대한 소스파일을 작성해줘야 한다.

그리고 패키지에 관련한 information, 즉 xml 파일이나 빌드를 위한 CMakeList 파일을 편집해주고, 그 이후에 빌드하고, 최종적으로 실행하는 순서로 작업을 진행한다.

ROS Topic 구현

  • publisher : 스탠다드 message (따로 정의 하지 않고 기존에 정의되어 있는 데이터 타입을 이용)
    topic_exam_pub

  • subscriber : 그 정보를 받아 화면에 출력
    topic_exam_sub

순서

  1. Create Package
  2. Create & Write two Nodes
  3. Edit Package Information
  4. Build
  5. RUn

Create Package

workspace 상에서 패키지를 만들어야 함.

  • verify /home/catkin_ws/src is exist
  • create your first package - "topic_exam" in this case
catkin_create_pkg [package name] std_msgs roscpp
//스탠다드 메시지, roscpp 를 사용할 것이다.  

그리고 src 폴더 안에 topic_exam_pub.cpp, topic_exam_sub.cpp
두 개의 파일을 생성해서 코드를 작성한다.

topic_exam_pub

#include "ros/ros.h"
#include "std_msgs/String.h"

#include <sstream>

int main(int argc, char **argv){
	ros::init(argc, argv, "topic_exam_publisher");
    ros::NodeHandle n;
    
    ros::Publisher topic_exam_pub = n.advertise<std_msgs::String>("topic_exam_message", 1000);
    ros::Rate loop_rate(10);
    
    int count = 0;
    while(ros::ok()){
    	std_msgs::String msg;
        std::stringstream ss;
        ss << "hello world" << count;
        msg.data = ss.str();
        ROS_INFO("%s", msg.data.c_str());
        topic_exam_pub.publish(msg);
        ros::spinOnce();
        loop_rate.sleep();
        ++count;
    }
	return 0;
}

주석

ros::init(argc, argv, "topic_exam_publisher");
//
master 한테 topic_exam_publisher 라는 이름으로 노드를 등록해달라고 요청함. 
파일 이름으로 노드를 등록하는 게 아니라, rosinit 의 세 번째 argument 로 등록함. 
ros::NodeHandle n;
//
핸들을 이용해 노드에 대한 동작이나 특성을 지원할 수 있음. 
노드에 대한 접점, 포트가 됨. 
ros::Publisher topic_exam_pub = n.advertise<std_msgs::String>("topic_exam_message", 1000);
//
n.advertise: 어떤 것을 publish 할 것인지 미리 얘기하는 것.
subscriber 에게 이 노드의 주소를 미리 알려주기 위함. 
등록한다고 생각하면 좋다. 

topic_exam_sub

#include "ros/ros.h"
#include "std_msgs/String.h"

void getCallBack(const std_msgs::String::ConstPtr& msg){
	ROS_INFO("I heard : [%s]", msg->data.c_str());
}
int main(int argc, char **argv){
	ros::init(argc, argv, "topic_exam_subscriber");
    ros::NodeHandle n;
    ros::Subscriber topic_exam_sub = n.subscribe("topic_exam_message", 1000, getCallback);
    ros::spin();
    
    return 0;
}

주석

subscriber 도 하나의 노드가 여러 topic 을 subscribe 할 수 있다.

하지만, 보내는 애는 내가 원하는 시간에 보낼 수 있지만 subscriber 는 언제 내가 구독한 메시지가 들어올 지 모르는 일이므로,
이에 대한 callback function 을 미리 정의해 둔다.
spin() 은 interrupt 가 걸릴 때 까지 대기하는 것이다.

  1. 노드를 등록한다.
  2. 노드 핸들러를 만든다.
    .
    .

build 를 할 수 있는 시스템 만들기

처음에 패키지를 만들었을 때 있던 파일

  1. CMakeLists.txt
  2. package.xml : 패키지에 대한 정보를 담고 있음. ex) build 는 catkin 으로 하고 roscpp 를 사용하고.. 등등

CMakeLists.txt

cmake_minimum_required(VERSION 3.0.2)
project(topic_exam)

find_package(catkin REQUIRED COMPONENTS roscpp std_msgs)

catkin_package(CATKIN_DEPENDS roscpp std_msgs)

include_directories(include ${catkin_INCLUDE_DIRS})
add_executable(topic_exam_pub src/topic_exam_pub.cpp)
target_link_libraries(topic_exam_pub ${catkin_LIBRARIES})

add_executable(topic_exam_sub src/topic_exam_sub.cpp)
target_link_libraries(topic_exam_sub ${catkin_LIBRARIES})

실행

rosrun [패키지이름] [노드이름]
rosrun topic_exam topic_exam_pub
rosrun topic_exam topic_exam_sub

현재 활성화 된 토픽이 뭐가 있는지를 보려면

rostopic list

0개의 댓글