본문 바로가기

FOSCAR-(Autonomous Driving)/ROS 스터디

[2023 ROS 스터디] 조영상 #3주차 - ROS 기본 프로그래밍

반응형

*강의 출처 : 로보티즈(표윤석 님)

스터디 내용 중 혹시 틀리거나 잘못된 부분이 있을 때 정말 가감 없이 지적해 주시면 부족한 제가 성장하는데 큰 도움이 될 것 같습니다. 감사합니다!

 

이번 강의는 1개밖에 되지 않았지만 실습이 굉장히 많아서 많은 시간을 투자하게 되었던 것 같다. 

 

ROS 프로그래밍 전에 알아둬야 할 사항 

 

표준 단위 : SI 단위 사용 (미국에서 ROS를 개발했지만 글로벌화를 위해 SI를 사용)

 

표준 단위 표준 위키 문서 : https://www.ros.org/reps/rep-0103.html 

 

좌표 표현 방식 :  우리가 수학시간에 사용하는 3차원 직교좌표계를 생각하면 된다. 

 

출처 : https://ko.wikipedia.org/wiki/3%EC%B0%A8%EC%9B%90

x : forward , y : left , z : up

 

회전에 대한 표현 기준은 다음과 같다.(오른손 법칙)

 

출처 :  https://m.blog.naver.com/at3650/220080876153

 

 

프로그래밍 규칙(명명 규칙) : ROS에서 다룰 패키지나 토픽, 파일, 변수, 클래스등의 이름들을 어떤 규칙으로 지어야 서로 알아보기 쉬운지 wiki에 나와있다. 

 

ROS cppstyleguide : https://wiki.ros.org/CppStyleGuide 

 

ex) 대상(패키지) - 명명 규칙(under_scored) - 예제(first_ros_package)

 

위의 명명법이나 표준 규약을 사용되는 이유가 내가 만든 프로그램을 공식패키지로 만들고 싶을 때 꼭 지켜야 하는 사항이기 때문이다. 혹은 공개된 패키지와 내가 만든 패키지를 함께 사용해야 할 때 호한되어야 하기 때문에 지켜야 한다.  

 

메시지 통신 방식(topic, service, action, parameter) 간단하게 복습

 

실습 시작

 

cd : change directory : 현재 살피고 있는 폴더를 바꿔라.

~ : home 폴더

즉, 홈 안에 있는 catkin_ws안에 있는 src 폴더로 이동해라.라는 명령이다.

 

before
after

패키지 폴더가 만들어졌다.

 

include, src파일에는 모두 비어있다.

그러나 CmakeLists 파일과 package.xml이라는 파일에는 무언가 적혀 있는 것을 확인할 수 있다. 

 

패키지를 만들기 전에 기본적으로 설정되어있어야 할 사항들이 기술되어 있는데 일단 기본적으로 우리가 명령어를 통해 언급해 주었던 사항들(의존성 cpp관련)이 포함되어 있는 것을 확인할 수 있다.

 

명령어 ls를 통해서도 해당폴더에 어던 파일들이 존재하는지 확인핳 수 있다.

 

우리는 이제 기본 설정들이 적혀있는 문서를 조금 수정해 줄 필요가 있다.

 

먼저 package.xml을 수정해줘야 하는데 우선 이게 뭔지 파악하자.

 

Package.xml

 

패키지 설정파일이고 ROS의 필수 설정파일이다. 

 

패키지의 이름, 저작자, 라이선스, 의존성 패키지등을 기술하고 있다.

 

<? 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과 author가 동일인물인 경우가 있지만 나중에 업데이트하다가 maintainer가 바뀌어서 관리 될 수도 있다.
<url type="website">http://www.robotis.com 
<url type="repository">https://github.com/ROBOTIS-GIT/ros_tutorials.git > 해당 깃헙 사이트에 들어오면 소스코드를 찾아볼 수 있다.(source)
<url type="bugtracker">https://github.com/ROBOTIS-GIT/ros_tutorials/issues > 이슈가 있을 때 해당사이트로 들어와서 토론하자.

 

이제 아래에 나오는 것들은 뒤에 depend라는 단어가 붙는 태그들인데 바로 의존성과 관련된 태그들이다.
<buildtool_depend>catkin</buildtool_depend> 빌드할 때 어떤 것을 쓸 거냐 (예전에는 rosbuild라는 것이 있었다. ros2는 또 다르다.)

 

아래 나온 태그들은 강의 동영상 내용과 강의 자료에 적힌 내용과 조금 다른데 일단 강의 자료에 적인 내용은 아래와 같다.
<depend>roscpp</depend>
<depend>std_msgs</depend>
<depend>message_generation</depend>
<export></export >
</package> 

 

 

강의 동영상에 적힌 태그들은 다음과 같다.

depend 앞에 build가 붙은 것은 빌드 할 때의 의존성이 걸리는 것

depend 앞에 run이 붙은 것은 run(실행) 할때의 의존성이 걸리는 것인데

 

대부분 두 개가 같은 것들이 태그 되지만 아래의 예시의 경우 조금 다른 점이 있다. (근데 결국 강의 자료에 있는 대로 했더니 아래처럼 두 번씩 적지 않아도 실행이 정상적으로 됐다.)

 

build 할 땐 message_generation이고, run 할 땐 message_runtime이다. // build 할땐 message_runtime이 필요없고 run할 때도 마찬가지로 messafe_generation이 필요 없기 때문이다.

 

<build_depend>roscpp</build_depend>  이번 토픽 튜토리얼에서는 C++언어를 쓸 것이기 때문에 C++을 쓸 때 필요한 API를 사용하기 위해 적어준 것이다.
<build_depend>std_msgs</build_depend> 이번 실습에서는 특별한 것(카메라정보, 회전속도 병진속도)이 아니라, standard message(bool, int32 등등) 쓸 것이기 때문이다.  
<build_depend>message_generation</build_depend> 우리가 기존의 메시지를 사용하는 것이 아니라 메세지를 만들어볼 것이기 때문이다.
<run_depend>roscpp</run_depend>
<run_depend>std_msgs</run_depend>
<run_depend>message_runtime</run_depend> 

 

 

 

위의 태그 중에서 패키지에 대한 간략한 설명을 적어주는 <description> 태그 부분은 나중에 공식패키지로 등록되었을 경우 위키의 설명으로 인용되기 때문에 공식패키지를 노리고 있다면 핵심내용을 간략하게 잘 적어줘야 한다.(자동으로 위키 사이트가 만들어질 수도 있음)

 

 

예를 들어 dynamixel_workbench 패키지를 확인해 보면

위의 빨간 상자 부분이 바로 description에서 적어 주었던 부분이 인용되어 사이트가 만들어질 때 사용된다. (검색 키워드로 사용됨)

 

그 아래의 조금 잘린 부분인 저작자, 라이선스 등등도 모두 package, xml에 적었던 것들이 그대로 인용된다.

 

CMakeLists.txt

cmake_minimum_required(VERSION 2.8.3) cmake버전이 2.8.3 이상이면 빌드하는데 큰 문제가 없다는 뜻이다.(지금 내가 쓰고 있는 버전은 3 이상일 것이다.)
project(ros_tutorials_topic) 아까 package.xml에서 설정했던 패키지 이름이랑 동일하게 적어줘야 한다.(

 

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

 

## 메시지 선언: MsgTutorial.msg
add_message_files(FILES MsgTutorial.msg) 새로 만들 메시지의 이름을 적어준다.(새로 메시지를 만들 때 사용되는 명령 add이다.)

 

## 의존하는 메시지를 설정하는 옵션이다.
## std_msgs가 설치되어 있지 않다면 빌드 도중에 에러가 난다.
generate_messages(DEPENDENCIES std_msgs) 메세지를 만들때 std_msgs를 포함할 것이다.라고 설정해 둔다.

 

## 캐긴 패키지 옵션으로 라이브러리, 캐킨 빌드 의존성, 시스템 의존 패키지를 기술한다.\

##라이브러리 같은 경우에는 일반적으로 패키지의 이름과 동일하게 한다.
catkin_package(
LIBRARIES ros_tutorials_topic  
CATKIN_DEPENDS std_msgs roscpp
)

 

## 인클루드 디렉터리를 설정한다.
include_directories(${catkin_INCLUDE_DIRS})  왼쪽에 나와있는 방식대로라면 기존에 설치되어 있는 각종 패키지들의 include 파일 들어 사용하는 것이다. 

만약에 include 파일을 개인적으로 갖고 있고 그걸 써야 한다면 다음과 같이 적어준다.

## include_directories(${catkin_INCLUDE_DIRS} include )  이렇게 했을 경우 우리가 처음에 패키지 생성 명령어로 include 파일과 src파일을 만들었을 때 include 파일이 비어있었는데 여기다가(include 파일) 내가 넣고자 하는 헤더파일을 넣으면 위의 명령어를 통해 그 헤더파일이 적용될 수 있게 된다.

 

이제 아래 적힐 부분들이 매우 중요하다. 실제 빌드와 아주 연관성이 큰 부분이다.

 

우리는 이 튜토리얼에서 토픽을 보내는 퍼블리셔 노드를 만들 것이고 그 토픽을 받는 서브스크라이버 노드를 만들 것이다. 

결국 두 개의 실행 파일 (토픽을 보내는 애, 받는 애)을 생성할 것이다. 그래서 각각의 실행 파일들을 빌드할 때의 옵션들을 아래 두 부분으로 나누어서 적은 것이다.

 

## topic_publisher 노드에 대한 빌드 옵션이다.
## 실행 파일, 타깃 링크 라이브러리, 추가 의존성 등을 설정한다.
add_executable(topic_publisher src/topic_publisher.cpp) topic_publisher라는 이름을 갖는 노드(실행파일의 이름)를 만들 것인데, 그 노드를 만들 때 참고해야 할 소스코드는 src/topic_publisher.cpp이다.(src폴더에 담긴 topic_publisher.cpp)


add_dependencies(topic_publisher ${${PROJECT_NAME}_EXPORTED_TARGETS} 위의 퍼블리셔를 만들 때 참고해야 하는 dependency들(이 예제에서는 ${${PROJECT_NAME}_EXPORTED_TARGETS)을 적어두었다. 대표적으로는 메시지를 빌드하게 된다. 

 

우리가 이따가 MsgTutorial.msg라는 메시지 파일을 만들것인데 이것은 자동으로 해당 메세지를 쓸 수 있는 헤더파일을 생성하게 된다. 이것을 빌드 하고 나서 바로 위에 적힌 퍼블리셔노드를 빌드해야하는 순서이다. 즉 빌드에 순서를 따라줘야 하는데 add_dependency를 통해 메세지 파일이 먼저 빌드되도록 한 후에 퍼블리셔노드가 빌드되도록 해준다. 

 


${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})  이건 설명 안 하심

 

Message 파일 만들기

 

메시지를 만들기에 앞서서 새로운 명령어 하나를 실습하게 된다. 

 

roscd : 이것은 리눅스 명령어 cd와는 조금 다른데 cd의 경우 내가 찾고자 하는 파일이 존재하는 경로를 적어줘야 하지만 roscd 패키지이름이라고 적어주면 해당 패키지가 있는 파일로 자동으로 change directory 해준다. 

 

$ mkdir msg : msg라는 폴더를 만든다.

 

time이라는 메세지 형식을 같는 stamp라는 메세지를 넣어준 것이고 int32 형식을 갖는 data라는 메세지를 새로 만들어줬다.

int32는 자료형, data는 메시지 이름이다. 마치 C언어의 변수 선언과 유사함.

 

int32 말고도 bool, float 등등을 사용할 수 있다(맨 위에 사이트 참고)

 

뭘 하기 위해 위의 메시지 타입을 넣어줬냐 하면 바로 메시지를 보낼 때 그 시각을 넣어서 보내주기 위해 위의 형식을 사용하였다. (time) 

 

data를 넣어 보내기 위해 int32사용함.

 

퍼블리셔 노드 작성

 

#include "ros/ros.h" // ROS 기본 헤더파일 //각종 ROS관련 API들을 사용할 수 있도록 해준다. 예전의 windows.h와 유사.

아래 소스코드에서 ros::~이런식으로 되어있는 부분을 사용하기 위함이다. 
#include "ros_tutorials_topic/MsgTutorial.h"// MsgTutorial 메시지 파일 헤더(빌드 후 자동 생성됨) 아까 CMake파일 수정할 때 메세지파일먼저 빌드하고 블리셔 노드를 빌드하라고 했는데 메세지 파일이 빌드되면서 메세지 파일의 헤더파일이 자동생성되고 이를 활용해야하기 때문에 CMakeLists에서 의존성으로 꼭 적어주었던 것이다.(중요 옵션)

 

 
int main(int argc, char **argv) // 노드 메인 함수
{
ros::init(argc, argv, "topic_publisher"); // 노드명 초기화//노드는 고유의 이름이어야 하고 때문에 중복으로 쓸수 없다. 

//ros마스터가 실행되고 다른 노드가 실행되면 마스터에게 보내줘야 하는 정보들이 노드의 이름 ip,포트 번호등등을 보내주게 된다. 때문에 이러한 내용들이 아래에 모두 기술 되어있어야 한다. 그런데 ip와 port번호는 기술해주지 않아도 된다. 왜냐하면 노드가 실행될 때 그 머신에서의 ip주소가 넘겨질 것이고 port번호는 임의로 할당해서 넘겨주게 되어있다.(개발자가 특정 port를 사용하도록 정할 수 도 있다.) 


ros::NodeHandle nh; // ROS 시스템과 통신을 위한 노드 핸들 선언


// 퍼블리셔 선언(이 노드는 퍼블리셔의 역할을 한다고 선언해 주는것),

// ros_tutorials_topic 패키지의 MsgTutorial 메시지 파일을 이용한(퍼블리셔하는 메세지의 형태를 기술하게 됨)
// 퍼블리셔 ros_tutorial_pub 를 작성한다. 토픽명은 "ros_tutorial_msg" 이며,
// 퍼블리셔 큐(queue) 사이즈를 100개로 설정한다는 것이다(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 파일을 만들때 stamp를 만들었기에 멤버 변수로 사용가능)
msg.data = count; // count라는 변수 값을 msg의 하위 data 메시지에 담는다(아까 msg 파일을 만들때 data를 만들었기에 멤버 변수로 사용가능)
ROS_INFO("send msg = %d", msg.stamp.sec); // stamp.sec 메시지를 표시한다 ROS_INFO는 printf같은 함수이다. 이외에도 목적에 따라 단순 정보전달(ROS_INFO), warning, 에러 등등으로 출력함수를 여러개 제공한다.  나중에 에러 값만 보고 싶을 땐 에러출력함수만 활성화시킨 후 실행시키면 되기 때문에 이런 경우에 활용하게 된다. 


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(); // 위에서 정한 루프 주기에 따라 슬립에 들어간다(위에서 얼마만큼의 주기로 메세지를 보낼지 정한 대로 쉬어준다,. 10Hz)
++count; // count 변수 1씩 증가
}
return 0;
}

 

서브스크라이버 노드 작성

 

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

 

위에서 퍼블리셔와 서브스크라이버 노드의 소스코드를 한번 작성해 보았는데 여기서 알아두어야 할 사항은, 반드시 노드 하나당 서브스크라이버 하나, 혹은 노드 하나당 퍼블리셔 한개만 만들 수 있는 것은 아니다. 하나의 노드에 복수의 퍼블리셔와 복수의 서브스크라이버의 역할을 만들어줄 수 있다. 하나의 노드에서 다양한 역할을 수행 할 수 있는 것이다.  

빌드 $cm

빌드 하는 과정에서 나오는 스크립트들을 확인해보면 우리가 만든 .msg파일를 C++,Javascript,Python등등의 언어로 생성해주는 것을 확인해 볼 수 있다. 즉, 다른 언어에서도 해당 메세지를 쓸 수 있도록 빌드해놓는다. 

(물론 모든 언어에 대한 생성을 임의로 막고 내가 생성하고자 하는 언어에 대한 생성만 하도록 해주도록 설정할 수 있다.)

 

마지막 부분을 보면 녹생 글자로 최종적으로 실행파일을 만들었다는 스크립트를 확인할 수 있다. 

 

메세지, 그리고 퍼블리셔, 서브스크라이버 소스코드 파일들은 catkin_ws의 src폴더에 있다. 그렇다면 위의 cm명령으로 인해 생긴 실행 파일은 어디에 있을까?

 

바로 catkin_ws의 build와 devel 폴더 안에 있다. 앞서서 메세지파일을 빌드하면 자동적으로 메세지 파일에 과련된 헤더파일이 생성된다고 설명했었다. 이를 확인해보자.

 

 

 

그리고 퍼블리셔와 서브스크라이버의 실행파일은 다음의 폴더안에 존재하게 된다.

 

퍼블리셔 실행 (rosrun)

단, 이때 rqt_graph를 확인 했을때 노드 하나만 실행되었으므로 퍼블리셔 노드가 위의 터미널에 나온대로 메세지를 발행 하는 것이 아니라 아직은 단순히 ROS_INFO만 하고 있는 것이다. (근데 아래의 rostopic list, info를 확인해보면 발행은 되고 있는 듯하다. 내 생각) 

 

현재 발생되고 있는 모든 토픽
ros_tutorial_msg라는 토픽 메세지의 정보

서브스크라이버 실행

 

서브스크라이버 & 퍼블리셔 노드 함께 확인

 

 

서비스

패키지 기본 틀 생성

package.xml 수정

 

CMakeLists.txt 수정

퍼블리셔, 서브스크라이버의 CMakeLists.txt 를 수정 할 때에는 메세지 파일을 추가했지만 여기선 서비스파일(SrvTutorial.srv)를 추가해준다. 그리고 이 메세지가 의존하는 메세지를 적어준다. 

 

여기선 두개의 실행파일을 만들 것인데 하나는 서버, 나머지 하나는 클라이언트이다. 

 

서비스 파일 작성

---기준으로 위에는 요청하는 메세지 형태(서비스 클라이언트가 쓴다.), 아래는 응답하는 메세지 형태(서비스 서버가 사용한다.)

 

서비스 노드 작성

1, 서비스 서버

 

 

2. 서비스 클라이언트

이제부터 위에서 퍼블리셔와 서브스크라이버를 수행했던 것 처럼 각각 rosrun을 수행해줘도 되지만 강의에서는 각의 자료를 git clone해서 보다 더 간편하게 진행하라고 했다. 

해당 git사이트에는 가으이에서 쓰인 모든 튜토리얼 패키지가 담겨있고 내가 기존에 만들었던 것과 이름이 중복 되는 것들도 있기에 내가 만든 것들(catkin_ws/src)은 music폴더에 옮겨두었다.

 

git clone

 

cm

rosrun (서비스 서버)

 

클라이언트의 요청이 있을 때까지 대기상태로 있는 것이다. 

 

클라이언트가 2와 3이라는 서비스를 요청했고 그에 대한 응답으로 결괏값(프로그램상에서 덧셈으로 응답하도록 함) 5를 정상적으로 응답받았다. 

 

그리고 연결이 끊기게 된다. (끊기도록 프로그램을 짰고 끝나지 않게 하도록 할 수도 있다.)

 

서비스의 경우에는rqt_graph로 확인할 수가 없다. (요청을 받고 순간적으로 응답을 보내고 종료하기 때문)

 

클라이언트 서버를 이용하지 않고 서비스 요청 

rqt를 사용하여 서비스 요청

또한 부가적으로 앞서서도 언급했듯이 하나의 노드에 복수의 서비스 클라이언트, 서버, 퍼블리셔, 서브스크라이버 등등의 역할을 함께 하게 할 수 있다.

 

파라미터

 

외부의 파라미터를 변경함에 따라 우리가 기존에 만들었던 서비스의 사칙연산 방법이 달라지도록 실험해볼 것이다.

 

그래서 service_server.cpp파일을 수정해 줘야하는데 주요 수정 부분은 다음과 같다.

 

일단 default는 더하기로 하고 이후 switch문을 위해 사칙연산들을 define해놓는다.

 

사칙연산 정의
초기 설정을 더하기로한다.

 

추가적으로 아까 서비스를 만들 땐 서비스 요청이 오기 전까지는 무조건 대기하는 것이였다. 하지만 이번에는  중간중간에 파라미터를 확인하려고 루프를 돌게 해놨다. 

while문 안에서 getParam을 통해서 계속 파라미터 값을 받아오게 된다. 

 

또한 원래는 ros::spin()만 하게 되면 계속 대기하는 것이지만

이번에 사용된 ros::spinOnce()는 한번 콜백함수 처리 루틴을 하고 r.sleep()이 실행되게 된다(아까 10이라고 설정해놓음).10Hz의 속도로 계속 반복하게 되는 것이다.(0.1초 만큼 쉬고 다음 루틴 시행)  

 

정석대로라면 이대로 서비스 서버, 클라이언트의 소스코드를 수정해주면 되지만 강의에서는 git을 통해 parameter라는 패키지를 따로 만들어서 제공해주었다. 

 

파라미터 패키지를 실행함으로써 해당 실습을 진행해 보았다. 

 

우측이 서버, 좌측이 클라이언트

파라미터 변경해보기 (뺄셈으로 변경)

 

 

roslaunch

$ roslaunch 패키지명 roslaunch파일

 

하나 이상의 노드를 동시에 실행시킬 수 있다. (실제 우리가 거대 프로그램을 만들면 굉장히 많은 노드를 실행시켜야 하기 때문에 유용하다.)

 

뿐만 아니라 패키지의 매개변수, 노드이름, 노드 네임스페이스 설정, ROS_ROOT, ROS_PACKAGE_PATH,환경 변수 변경 등의 옵션을 붙일 수 있다. 

 

roslaunch는 xml기반이며 태그별 옵션을 제공한다.  .launch라는 파일을 사용하여 설정한다.  

 

방법 1. 

노드의 이름은 고유해야하기 때문에 숫자를 붙여준다. 

 

방법 2. 

이때는 토픽 명과 노드명이 달라지게 된다. 

 

roslaunch의 여러가지 태그들

 

가장 많이 사용되는 태그는 <arg>이다. 외부에서 파라미터를 주어을때 소스코드의 변수를 그 파라미터로 변경시켜줄수 있다. 

 

 

 

반응형