본문 바로가기

FOSCAR-(Autonomous Driving)/ROS 스터디

[2023 ROS 스터디] 정혁제 #3주차 - ROS 기본 프로그래밍

반응형

CHAPTER 7-1 TOPIC

 

일단 전체적인 순서는

1. catkin_ws/src 폴더 생성

2. src 안에 패키지 생성

3. 파일 2개 수정

4. 메세지 파일 작성

5. 퍼블리셔 노드 작성

6. 서브스크라이버 노드 작성

7. ROS 노드 빌드 ... ............ 뒤에 더 있는데

나같은 경우 빌드 생성할때 오류가 계속해서 떴다

해결방안은

1. 파일 수정 내용 정확이 입력하기 (유튜브에 더보기 링크가면 ppt 자료 있으니까 복붙하자!)

2. catkin_ws 폴더 생성하고, 패키지 생성하기 전에 빌드를 미리 해놓은 경우!! -> 안되니까 빌드는 나중에 하자

3. 안되면 그냥 밀고 처음부터 천천히 다시해보자. 나도 4번째 도전 끝에 성공했다...

4. 그래도 안되면 ros 지우고 재설치!

 

위에 내용들은 이제 알아가보면 되고, 

---이제 시작----

1) 패키지 생성.

$ catkin_create_pkg ros_tutorials_topic message_generation std_msgs roscpp - 패키지를 생성해주도록 하자!

 

catkin_create_pkg : package를 생성하는 명령어

ros_tutorials_topic : package 이름!

message_generation , std_msgs , roscpp : 의존성 패키지들

-> message_generation , std_msgs, roscpp 같은 패키지를 의존하고, 이름은 ros_tutorials_topic 을 가진 패키지를 생성해라!

 

(생성된 파일들을 보면)

include → 헤더 파일 폴더

src → 소스 코드 폴더

CMakeLists.txt → 빌드 설정 파일

package.xml → 패키지 설정 파일이 들어가는 것을 확인 할 수 있다.

 

 

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

$ gedit package.xml

이제 package.xml을 복붙하자!!

 

ROS의 필수 설정 파일 중 하나인 package.xml은 패키지 정보를 담은 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> ##나중에 가면, 저자와 maintainer가 달라진다.
<url type="website">http://www.robotis.com</url> ##여기 들어가면 된다!
<url type="repository">https://github.com/ROBOTIS-GIT/ros_tutorials.git</url> ##여기 들어오면 찾아볼 수 있어!
<url type="bugtracker">https://github.com/ROBOTIS-GIT/ros_tutorials/issues</url > ##문제가 있으면 알려줘!
<buildtool_depend>catkin</buildtool_depend> ##빌드할때 툴을 말한다.
<depend>roscpp</depend> ##c++ 사용할 예정이라는 뜻
<depend>std_msgs</depend> ##standard message 사용할 예정 
<depend>message_generation</depend> ##메세지를 직접 만들기 위해, 따로 적어주어 놓았다.
<export></export >
</package>

 

3) 빌드 설정 파일(CMakeLists.txt) 수정

cmake_minimum_required(VERSION 2.8.3) 

## 패키지명과 동일한 이름으로, project안에 넣어준다. (하나의 룰)
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)
## 의존하는 메시지를 설정하는 옵션이다. -> MsgTutorial.msg 만들 때 의존성이 있는 std_msgs 언급
## 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) ## topic_pulisher실행파일을 만들 예정인데, 이때 src/topic_publisher.cpp를 의존해서 만들어라!!
add_dependencies(topic_publisher ${${PROJECT_NAME}_EXPORTED_TARGETS}
${catkin_EXPORTED_TARGETS}) ##먼저 메세지 파일이 있다면, 그 메세지 파일 빌드하고나서, 실제 실행가능한 topic_publisher를 빌드하고 실행 -> 왜냐하면, publisher.cpp에는 메세지 파일의 헤더파일이 들어있다.(즉, 메세지 파일이 빌드되고, header file 이 생성되어야만 topic_publisher.cpp가 실행 가능하기 때문) 
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) 메시지 파일 작성

앞서 CMakeLists.txt 파일에 다음과 같은 옵션을 넣었다.

-> add_message_files(FILES MsgTutorial.msg) 

노드에서 사용할 메시지인 MsgTutorial.msg를 빌드할 때 포함하라는 이야기이다!!

$ mkdir msg → ros_tutorials_topic 패키지에 msg라는 메시지 폴더를 신규 작성

$ cd msg → 작성한 msg 폴더로 이동

$ gedit MsgTutorial.msg → MsgTutorial.msg 파일 신규 작성 및 내용 수정

time stamp
int32 data

두줄 입력하고 저장해주자 !

메시지 타입은 time과 int32 이외에도 bool, int8, int16, float32, string, time, duration 등의 메시지 기본 타입과 ROS 에서 많이 사용되는 메시지를 모아놓은 common_msgs 등도 있다. 여기서는 간단한 예제를 만들어 보기 위한 것으로 time과 int32를 이용하였다.

$ cd .. → ros_tutorials_topic 패키지 폴더로 이동

 

5) 퍼블리셔 노드 작성

앞서 CMakeLists.txt 파일에 다음과 같은 실행 파일을 생성하는 옵션을 주었다.

-> add_executable(topic_publisher src/topic_publisher.cpp)

src 폴더의 topic_publisher.cpp라는 파일을 빌드하여 topic_publisher라는 실행 파일을 만들라는 이야기이다.

$ 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_tutorials_topic 패키지의 MsgTutorial 메시지 파일을 이용한
// 퍼블리셔 ros_tutorial_pub 를 작성한다. 토픽명은 "ros_tutorial_msg" 이며,
// 퍼블리셔 큐(queue) 사이즈를 100개로 설정한다는 것이다(1로 해도 무방)
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.nsec 메시지를 표시한다
ROS_INFO("send msg = %d", msg.stamp.nsec); // stamp.sec 메시지를 표시한다
ROS_INFO("send msg = %d", msg.data); // data 메시지를 표시한다

ros_tutorial_pub.publish(msg); // 메시지를 발행한다
loop_rate.sleep(); // 위에서 정한 루프 주기에 따라 슬립에 들어간다(0.1초마다 while문이 돌아간다)
++count; // count 변수 1씩 증가
}
return 0;
}

 

 

이제, 위의 파일을 분석해보자!!

1. ros::init(argc, argv, "topic_publisher"); - 노드는 고유의 것. 노드명을 처음 초기화 시켜주자!

2. ros::NodeHandle nh; - 노드 핸들 선언! 

3. ros::Publisher ros_tutorial_pub = nh.advertise<ros_tutorials_topic::MsgTutorial>("ros_tutorial_msg", 100); - 이 노드 안에 publisher를 만들자! 메세지의 형태로는  MsgTutorial을 사용할 것이며, topic의 이름은 ros_tutorial_msg 로 할 것이다.

5. 노드명, 메세지의 형태, 메세지의 이름 3개 정해주는 것이 제일 중요하다!!

6. 100은 queue 사이즈로, 시스템이 늦어지면, queue사이즈만큼 쌓아두었다가 publish해준다. (기본적으로는 1로 해도 된다)

7. ros::Rate loop_rate(10); - 루프 주기를 설정해주자. 10hz를 의미한다.(0.1)

8. ros_tutorials_topic::MsgTutorial msg; - 보낼 메세지를 선언해준다. Msg Tutorial 형식으로 msg라는 이름을가진 메시지를 만들어 준다! 이제 msg라는 변수를 사용해보자.

9. int count = 0; - 변수를 임의로 설정!

 

이제 while문을 파고들어 보자!!

10. while (ros::ok()) - 외부에서 프로세스를 죽이지 않는 이상 계속 돌도록 설정한다.

11. msg.stamp = ros::Time::now(); // msg.data = count;  - 우리 메세지 만들었잖아. MsgTutorial ! 그안에 stamp,와 data가 있으니까 멤버 변수로 stamp와 data를 사용할 수 있다. stamp에서는 함수를 불러온 시간을 기술하게 된다(저장). data에서는 count값이 들어간다.

 

-ROS에서는 printf 대신에 ROS_INFO를 사용한다!

12. ROS_INFO("send msg = %d", msg.stamp.sec);   -  stamp.sec 메시지를 표시한다
13. ROS_INFO("send msg = %d", msg.stamp.nsec); - stamp.nsec 메시지를 표시한다
14. ROS_INFO("send msg = %d", msg.data); - data 메시지를 표시한다

15. ros_tutorial_pub.publish(msg);  -  메시지를 발행한다

16. loop_rate.sleep(); - 위에서 정한 루프 주기에 따라 슬립에 들어간다(0.1초마다 쉰다!!)

17. ++count;  -  count 변수 1씩 증가

결국, msg는 보내는 시간과 count값을 1씩 증가시켜서 보내준다!

 

 

6) 서브스크라이버 노드 작성

앞서 CMakeLists.txt 파일에 다음과 같은 실행 파일을 생성하는 옵션을 주었다.

-> add_executable(topic_subscriber src/topic_subscriber.cpp)

• 즉, topic_subscriber.cpp라는 파일을 빌드하여 topic_subscriber라는 실행 파일을 만들라는 이야기 

$ 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;
}

 

중요 3가지

- 노드명

- 토픽 이름

- 받을 토픽의 형태

e

아까 위에서 본 publihser와 비슷한 개념이다. 

우선 main함수부터 살펴보면, 

1.ros::init(argc, argv, "topic_subscriber"); - 노드명(topic_subscriber)을 초기화해준다.

2.ros::NodeHandle nh; - 노드 핸들을 설정해준다.

3.ros::Subscriber ros_tutorial_sub = nh.subscribe("ros_tutorial_msg", 100, msgCallback); - subscriber 선언을 해주자. topic은 ros_tutorial_msg를 받고, queue사이즈는 100이다. 이 topic을 받았을 때, msgCallback함수를 실행하도록 설정해주었다.

4.ros::spin(); - callback 함수 호출을 위한 함수. 메세지가 도착하기 전까지는 대기상태로 있는다. 아무것도 안하고. 메세지가 도달하면 위의 함수를 실행해준다.

 

다시 위로 돌아가자.

5.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 메시지를 표시한다
}

이제 보이는가? 방금 전 callback 함수를 지정해준 것이다. 받은 메세지를 출력하도록 설정해준다.

중요한 것은, 하나의 노드에 publisher와 subscriber가 몇개가 들어가든 상관이 없다.

그냥, 노드는 집인 것이고, publisher는 데이터를 던지는 사람, subscriber는 데이터를 받아오는 사람이라 생각하면 쉽다!

 

7) ROS 노드 빌드

다음 명령어로 ros_tutorials_topic 패키지의 메시지 파일, 퍼블리셔 노드, 서브스크라이버 노드를 빌드하자.

$ cd ~/catkin_ws → catkin 폴더로 이동

$ catkin_make → catkin 빌드 실행

 < [참고] 파일시스템 >

• ros_tutorials_topic 패키지의 소스 코드 파일: ~/catkin_ws/src/ros_tutorials_topic/src

• ros_tutorials_topic 패키지의 메시지 파일: ~/catkin_ws/src/ros_tutorials_topic/msg

• 빌드된 결과물은 /catkin_ws의 /build와 /devel 폴더에 각각 생성!! (원본 src코드에서는 실행관련파일이 없다)

• /build 폴더에는 캐킨 빌드에서 사용된 설정 내용이 저장

• /devel/lib/ros_tutorials_topic 폴더에는 실행 파일이 저장

• /devel/include/ros_tutorials_topic 폴더에는 메시지 파일로부터 자동 생성된 메시지 헤더 파일이 저장

 

8) 퍼블리셔 실행

$ rosrun ros_tutorials_topic topic_publisher

ROS 노드 실행 명령어인 rosrun을 이용하여, ros_tutorials_topic 패키지의 topic_publisher 노드를 구동하라는 명령어

(실행 안되면 roscore 켰는지 확인 꼭꼭 하자!!)

그러면 화면에 데이터값들이 막 뜨기 시작한다!!! 

이때 착각하면 안되는 것이 publish를 하고 있지 않다는 중이다! (화면에는 그냥 printf만 하는 중이다)

왜냐하면, 받는 사람이 없는데 누가 계속 물체를 던진다고 해서 과연 물체를 전달한다고 생각할 수 있을까? 그건 아닐 것이다.

받는 사람이 있어야 물건을 "전달"해줄수 있는 것이다.

rostopic list를 실행시키면 ros_tutorial_msg라는 토픽이 있는 것을 확인할 수 있다.

rostopic info /ros_tutorial_msg를 실행시켜주면, 이름과 타입, 그리고 publishers와 subscribers를 확인할 수 있다.

rostopic list와 info 는 굉장히 많이 쓰이니 알아두면 좋을 듯하다.

rostopic echo /ros_tutorial_msg를 실행하면, 실시간으로 무슨 값을 뱉어내고 있는지 확인 가능하다. stamp와 data의 값이 들어오면 잘 되고 있는 중인 것이다!

 

9) 서브스크라이버 실행

$ rosrun ros_tutorials_topic topic_subscriber

• ROS 노드 실행 명령어인 rosrun을 이용하여, ros_tutorials_topic 패 키지의 topic_subscriber 노드를 구동하라는 명령어

수신을 잘 받는 것을 확인할 수 있다.

 

10) 실행된 노드들의 통신 상태 확인

$ rqt_graph

$ rqt [플러그인(Plugins)] → [인트로스펙션(Introspection)] → [노드 그래프(Node Graph)

맘에 든다. 앞으로도 pub-sub 간 topic이 잘 연결되어 잇는지 확인할려면 rqt_graph를 애용해 보도록 하자.

 

CHAPTER 7-2 SERVICE

하나의 폴더(catkin_ws)안에 다른 패키지로 여러번 빌드 할 수 있었다니.. 처음 알았다..

topic과 비슷하므로, 간단하게 본 후 넘어가자!

 

1) 패키지 생성

catkin_create_pkg로 패키지의 형태(껍데기)만 만들어 주자.

 

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

위와 동일하다

.

 

3) 빌드 설정 파일(CMakeLists.txt) 수정

project - 패키지의 이름

find_package - 요구되는 구성요소 패키지

아까는 메세지 선언을 했지만, 지금은 서비스파일을 하나 설정하자.

의존성 메시지를 설정하고, 패키지 옵션도 적어준다.

인클루드 디렉터리를 설정한다.

2개의 실행파일. service_server / service_client 두개 만들어 준다.

 

4) 서비스 파일 작성

앞서 서비스 파일을 설정한다고 했자나! 그거 이제 만들어보자.

int64 a

int64 b

---

int64 result

?? 뭐지.. "---"은 뭘까? -> 하이픈3개를 기준으로, 위는 request(서비스 요청), 아래는 response(서비스 응답) 나뉜다.

그냥 구분하는 구분자로 생각하자!

service server가 a,b를 받아서 result로 clinet에게 보내준다.

 

5) 서비스 서버 노드 작성

main 함수를 보면, node명을 service_server로 선언했다.

아까와 다르게, 이제 ServiceServer로 선언한다. 아까는 topic명, 지금은 서비스명으로 "ros_tutorial_srv"를 전달한다고 설정해준다. callback함수(서비스 명령이 있을때 실행) calculation 지정해준다.

ros::spin(); - 서비스 요청이 있을 때까진 쭉 대기한다. 요청이 들어오면 calculation을 실행한다.

calculation은 간단하게 말해서, a+b를 해서 result에 반영하는 것이다. 

 

6) 서비스 클라이언트 노드 작성

 

main함수를 보면, node명을 service_clinet로 초기화 해준다.

만약 입력값이 오류라면 처리해주기 위해 if문을 설정해준다.

ServiceClient를 선언한다. 이름은 ros_tutorials_service_client (요청하는 사람이다.) ros_tutorial_service 패키지의 SrvTutorial(아직 안만들어졌지만 곧 자동적으로 만들어질 파일)이 선언하는데 도와준다.

서비스명은 ros_tutorial_srv이다.

srv라는 이름으로 SrvTutorial 서비스 파일을 이용하는 서비스를 선언한다.

받은 값을 저장해준다.

서비스를 요청하고, 요청이 받아졋을 경우, 응답값을 표시하는 구문을 만들어준다. ( calculation이 true를 return해주면 정확하게 실행이 된다)

7) ROS 노드 빌드

8) 서비스 서버 실행

서비스 서버는 서비스 요청이 있기 전까지 아무런 처리를 하지 않고 기다리도록 프로그래밍하였다. 그러므로 다음 명령어를 실행하면 서 비스 서버는 서비스 요청을 기다린다

이거는 요청받고 난 후 사진~

9) 서비스 클라이언트 실행

< [참고] GUI 도구인 Service Caller 사용 방법 • ROS의 GUI 도구인 rqt를 실행하자. >

rqt 프로그램의 메뉴에서 [플러그인(Plugins)] → [서비스(Service)] → [Service Caller]를 선택하면 다음과 같은 화면이 나온다.

편하긴 한데 command 명령이 더 쉬워보인다.

CHAPTER 7-3 PARAMETER

 

1) 파라미터를 활용한 노드 작성

다음 순서대로 service_server.cpp 소스를 수정해보자

$ roscd ros_tutorials_service/src → 패키지의 소스 코드 폴더인 src 폴더로 이동

$ gedit service_server.cpp → 소스 파일 내용 수정

 

plus 는 1로, minus는 2로, multiplication 은 3, division은 4로 설정해준다.

기본 연산자는 plus로 설정!

g_operator에 따라서 어떤 연산을 할지 바꿔주자!

바뀐 부분은 nh.setParam("calculation_method",PLUS); plus로 초기화해준다.

아까는 ros::spin()으로 무조건 대기였는데, 이제는 parameter를 확인할려고 루프를 돌게 시켜놨다. (0.1초마다 계속 체크)

 

실행시키면 잘 나오는 것을 확인할 수 있다!

 

CHAPTER 7-4 ROSLAUNCH

 

• rosrun은 하나의 노드를 실행하는 명령어 이다.
• roslaunch는 하나 이상의 정해진 노드를 실행시킬 수 있다.
• 그 밖의 기능으로 노드를 실행할 때 패키지의 매개변수나 노드 이름
변경, 노드 네임스페이스 설정, ROS_ROOT 및 ROS_PACKAGE_PATH
설정, 환경 변수 변경 등의 옵션을 붙일 수 있는 ROS 명령어이다.
• roslaunch는 ‘*.launch’라는 파일을 사용하여 실행 노드를 설정하는데
이는 XML 기반이며, 태그별 옵션을 제공한다.
• 실행 명령어는 "roslaunch [패키지명] [roslaunch 파일]”이다.

 

1) roslaunch의 활용

• 이전에 작성한 topic_publisher와 topic_subscriber 노드의 이름을 바꾸어서 실행 해 보자. 이름만 바꾸면 의미가 없으니, 퍼블리쉬 노드와 서브스크라이버 노드를 각각 두 개씩 구동하여 서로 별도의 메시지 통신을 해보자.

• 우선, *.launch 파일을 작성하자. roslaunch에 사용되는 파일은 *.launch라는 파일명을 가지며 해당 패키지 폴더에 launch라는 폴더를 생성하고 그 폴더 안에 넣어야 한다. 다음 명령어대로 폴더를 생성하고 union.launch라는 새 파일을 생성해보자.

$ roscd ros_tutorials_topic
$ mkdir launch
$ cd launch
$ gedit union.launch

아래의 내용을 입력해 주도록 하자!

ros_tutorials_topic 안의 topic_publisher/subscriber의 노드를 꺼내서 각각 다른 노드명을 설정해준다.

총 4개의 노드가 실행되어야 한다. 

---------------------------------------------------------------------------------------------------------------------

• 태그 안에는 roslaunch 명령어로 노드를 실행할 때 필요한 태그들이 기술된다.

<node>는 roslaunch로 실행할 노드를 기술 하게 된다. 옵션으로는 pkg, type, name이 있다.

• pkg 패키지의 이름

• type 실제 실행할 노드의 이름(노드명)

• name 위 type에 해당하는 노드가 실행될 때 붙여지는 이름(실행명), 일반적으로는 type과 같게 설정하지만 필요에 따라 실행할 때 이름을 변경하도록 설정할 수 있다.

 

$ roslaunch ros_tutorials_topic union.launch --screen 을 실행해보자 (--screen)이 없으면 구분하기 힘드니, 꼭 붙여주자!

 

잘 나오는 것을 확인할 수 있다.

 

문제는  "퍼블리쉬 노드와 서브스크라이버 노드를 각각 두 개씩 구동하여 서로 별도의 메시지 통신하게 한다”는 처음 의도와는 다르게 rqt_graph를 통해 보면 서로의 메시지를 모두 서브스크라이브하고 있다는 것이다.

• 이는 단순히 실행되는 노드의 이름만을 변경해주었을 뿐 사용되는 메시지의 이름을 바꿔주지 않았기 때문이다.

• 이 문제를 다른 roslaunch 네임스페이스 태그를 사용하여 해결해보자

 

그럼 이제 아래와 같이 잘 나온다.

 

나가며...

수원 여행가는거 까먹고 있다가 급하게 호다닥 썼다.. 무려 5-6시간 걸린 것 같다.

앞으로 미리미리 해야겠다 ㅠㅠ

반응형