본문 바로가기

FOSCAR-(Autonomous Driving)/ROS 스터디

[2025 ROS 스터디] 황희찬 #3주차 - ROS 기본 프로그래밍

반응형

ros에서는 단위계로 SI표준 단위계를 사용한다. 또한, 3차원 좌표 표현 방식으로 양의 x방향은 forward방향 양의 y방향은 left방향 양의 z방향은 up방향을 가리킨다.

ros통신 방식 복습

간단하게 복습하면 토픽은 단방향 통신으로 퍼블리셔 노드가 서브스크라이버 노드에 어떠한 메시지를 보내주는 통신방식이고, 서비스는 양방향 통신으로 서비스 클라이언트 노드가 서비스 노드에 어떠한 요청이 들어가면 그에 대한 응답을 서비스 서버가 보내주는 통신 방식이다.

 

1.패키지 생성

ros에서 패키지란 특정 기능을 수행하는 코드, 실행 파일, 설정 파일, 메시지 정의를 포함하는 기본적인 구성 단위

$ 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     → 패키지 설정 파일

 

ros_tutorials_topic -> 패키지를 생성 

message_generation -> 사용자 정의 메시지

std_msgs -> ros 기본 메시지 타입

roscpp -> cpp로 노드 코드를 작성

 

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

ros의 필수 설정 파일 중 하나인 package.xml은 패키지 정보를 담은 XML 파일로 패키지 이름, 저작자, 라이선스, 의존성 패키지 등을 기술하고 있다.

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

3. 빌드 설정파일(CMakLists.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_generation std_msgs roscpp)

##메시지 선언 
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_subsciber 노드에 대한 빌드 옵션
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.메시지 파일 작성

빌드설정파일에서 다으모가 같은 옵션 코드를 넣었다.

add_message_files(FILES MsgTutorial.msg) -> 노드에서 사용할 메시지인 MsgTutorial.msg를 빌드할 때 포함하라는 뜻

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

 

time(메시지 형식), stamp(메시지 이름)

int32(메시지 형식), data(메시지 이름)

 

5.퍼블리셔 노드 작성

#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_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.data = count;
// 현재 시간을 msg의 하위 stamp 메시지에 담는다
// 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); // stamp.sec 메시지를 표시한다
// stamp.nsec 메시지를 표시한다
// data 메시지를 표시한다
 ros_tutorial_pub.publish(msg); // 메시지를 발행한다
 loop_rate.sleep(); // 위에서 정한 루프 주기에 따라 슬립에 들어간다
 ++count; // count 변수 1씩 증가
 }
 return 0;
}

6. 서브스크라이버 노드

#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. 퍼블리셔 노드 및 서브스크라이브 노드 실행

rosrun ros_tutorials_topic topic_publisher

rosrun ros_tutorials_topic topic_subscriber

8. rqt그래프로 노드간 연결 및 토픽전달 확인

반응형