본문 바로가기

FOSCAR-(Autonomous Driving)/ROS 스터디

[2023 ROS 스터디] 변준형 #3주차 - ROS 기본 프로그래밍

반응형

ROS 기본단위

* SI 단위 사용

 

좌표표현 방식

* X : forward / Y : left / Z : up

* 오른손 법칙 적용

 

# TOPIC (단방향 통신, 퍼블리셔, 서브스크라이버)

 

1. 패키지 설치 명령어

$ catkin_create_pkg ros_tutorials_topic message_generation std_msgs roscpp

2. 패키지 설정파일 수정

$ gedit package.xml
<? xml version="1.0"?>  
<package format="2"> 
<name>ros_tutorials_topic</name>
<version>0.1.0</version>
<description>ROS turtorial package to learn the topic</description>  
<license>Apache 2.0</license> 
<author email="pyo@robotis.com">Yoonseok Pyo</author> 
<maintainer email="pyo@robotis.com">Yoonseok Pyo</maintainer>
<url type="website">http://www.robotis.com 
<url type="repository">https://github.com/ROBOTIS-GIT/ros_tutorials.git >
<url type="bugtracker">https://github.com/ROBOTIS-GIT/ros_tutorials/issues > 
<buildtool_depend>catkin</buildtool_depend>
<depend>roscpp</depend>
<depend>std_msgs</depend>
<depend>message_generation</depend>
<export></export >
</package>

 

3. 빌드 설정파일 수정

cmake_minimum_required(VERSION 2.8.3) 
project(ros_tutorials_topic) 

## 캐빈 빌드를 할 때 요구되는 구성요소 패키지이다.
## 의존성 패키지로 message_generation, std_msgs, roscpp이며 이 패키지들이 
## 존재하지 않으면 빌드 도중에 에러가 난다.
find_package(catkin REQUIRED COMPONENTS message_generation std_msgs roscpp)

## 메시지 선언: MsgTutorial.msg
add_message_files(FILES MsgTutorial.msg)

## 의존하는 메시지를 설정하는 옵션이다.
## std_msgs가 설치되어 있지 않다면 빌드 도중에 에러가 난다.
generate_messages(DEPENDENCIES std_msgs)

## 캐긴 패키지 옵션으로 라이브러리, 캐킨 빌드 의존성, 시스템 의존 패키지를 기술한다.
catkin_package(
LIBRARIES ros_tutorials_topic  
CATKIN_DEPENDS std_msgs roscpp
)

## 인클루드 디렉터리를 설정한다.
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. 메시지 파일 작성

$ mkdir msg → ros_tutorials_topic 패키지에 msg라는 메시지 폴더를 신규 작성 → 작성한 msg 폴더로 이동
$ cd msg → MsgTutorial.msg 파일 신규 작성 및 내용 수정
$ gedit MsgTutorial.msg → ros_tutorials_topic 패키지 폴더로 이동
$ cd ..
time stamp
int32 data

 

5. 퍼블리셔 노드 작성

$ cd src → 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_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. 서브스크라이버 노드 작성

$ 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("recieve msg = %d", msg->stamp.sec); // stamp.sec 메시지를 표시한다
ROS_INFO("recieve msg = %d", msg->stamp.nsec); // stamp.nsec 메시지를 표시한다
ROS_INFO("recieve msg = %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 폴더로 이동 
$ catkin_make → catkin 빌드 실행

 

8. 퍼블리셔, 서브스 크라이버 실행

$ rosrun ros_tutorials_topic topic_publisher
$ rosrun ros_tutorials_topic topic_subscriber

실행화면

rqt_graph

 

# 서비스

 

앞의 토픽과 유사하게 서비스 또한 강의 과정을 따라 패키지, 빌드 파일 등을 강의 순서에 따라 수정해가면 됩니다.

토픽과의 차이점은 서비스 파일 작성시 나타납니다.

int64 a
int64 b
---
int64 result

토픽과 달리 int64 (메시지 형식), a, b (서비스 요청: request), result (서비스 응답: response), ---’ (요청과 응답을 구분하는 구분자)로 구성되어있습니다.

 

ROS 노드 빌드를 완료하고 서버를 실행하면 아래와 같은 화면이 나타납니다.

이때 파라미터에 2와 3의 값을 주면 5가 나타납니다.

따라서 서비스 클라이언트가 정상적으로 실행되는 것을 확인할 수 있습니다.

 

roslaunch 사용법

 

* rosrun

-> 하나의 노드를 실행하는 명령어

* roslaunch

-> 하나 이상의 정해진 노드를 실행

 

roslaunch의 활용

 1. launch 파일 작성

2.  roslaunch 실행 명령어 및 결과

\

3. rqt_graph

 

반응형