이번 포스팅에서는 ROS의 매개변수(parameter, 파라미터) 프로그래밍에 대해서 공부해보자. 참고한 링크는 다음과 같다.
https://cafe.naver.com/openrt/3111
우선 매개변수가 뭔지부터 다시 복습하자.
💡 매개변수(parameter)
노드에서 사용하는 매개변수로, 일종의 설정값이다. 디폴트값들이 부여되어있으며 실시간으로 읽기 및 쓰기가 가능해, 실시간으로 상황에 맞추어 설정을 변경할 수 있게 해주는 기능을 지ㅜ언한다.
매개변수와 관련된 명령어는 다음 포스팅을 참조하자.
https://velog.io/@hy_k/ROS-%EA%B3%B5%EB%B6%80%ED%95%98%EA%B8%B013-ROS-%ED%8C%8C%EB%9D%BC%EB%AF%B8%ED%84%B0%EC%99%80-%EA%B4%80%EB%A0%A8-%EB%AA%85%EB%A0%B9%EC%96%B4%EB%93%A4
앞에서 작성한 서비스 패키지를 수정해서, 서비스 요청으로 입력한 a와 b를 단순히 덧셈하는게 아니라 사칙연산 하도록 매개변수를 활용해보자.
우선 코드를 수정해야한다.
oroca_ros_tutorials 패키지로 들어가서, ros_tutorial_srv_server.cpp 파일을 다음과 같이 수정하자.
#include "ros/ros.h"
#include "oroca_ros_tutorials/srvTutorial.h"
#define PLUS 1
#define MINUS 2
#define MULTIPLICATION 3
#define DIVISION 4
// 사칙연산에 맞는 상수(const)를 선언한다.
int g_operator = PLUS;
bool calculation(oroca_ros_tutorials::srvTutorial::Request &req,
oroca_ros_tutorials::srvTutorial::Response &res){
// 서비스 요청이 있을 경우 이 함수를 사용한다.
switch(g_operator){
case PLUS:
res.result = req.a + req.b;
case MINUS:
res.result = req.a - req.b;
case MULTIPLICATION:
res.result = req.a * req.b;
case DIVISION:
res.result = req.a / req.b;
default:
res.result = req.a + req.b; break;
}
ROS_INFO("request: x=%ld, y=%ld", (long int)req.a, (long int)req.b);
ROS_INFO("sending back response: [%ld]", (long int)res.result);
// 서비스 요청에 사용된 a와 b값의 표시 및 서비스 응답에 해당하는 result 값 출력
return true;
}
int main(int argc, char **argv){
ros::init(argc, argv, "ros_tutorial_srv_server");
ros::NodeHandle nh;
nh.setParam("calculation_method", PLUS);
// 매개변수 초기 설정을 넣는다.
ros::ServiceServer ros_tutorial_service_server = nh.advertiseService("ros_tutorial_srv", calculation);
// 서비스 서버를 선언하고, 패키지 내부의 srv 파일을 이용한
// 서비스 서버 ros_tutorial_srv_server를 선언한다.
// 서비스명은 ros_tutorial_srv이며, 서비스 요청이 있을 경우 calculation이라는 함수를 실행한다.
ROS_INFO("ready srv server!");
ros::Rate r(10); //10hz 지정
while (1){
nh.getParam("calculation_method", g_operator); // 연산자를 매개변수 값으로부터 변경
ros::spinOnce(); // 콜백 함수 처리
r.sleep(); // 루틴 반복을 위한 슬립 처리
}
ros::spin();
}
달라진 부분을 분석해보도록 하자.
nh.setParam("calculation_method", PLUS);
calculation_method라는 이름의 매개변수를 PLUS라는 값으로 설정한다는 것이다. 여기에는 PLUS를 1로 정의했으니, 1로 설정된다. 참고로 매개변수 값은 정수, 실수, 논리형(boolean), 문자열, 딕셔너리, 리스트 등을 사용할 수 있다.
nh.getParam("calculation_method", g_operator);
이 부분은 매개변수를 불러와서 g_operator의 값으로 설정한다는 것이다. 따라서 위 코드에서 g_operator는 0.1초마다 매개변수의 값을 확인하여 서비스 요청으로 받은 값을 사칙연산 중 어떤 연산으로 처리할지에 대해서 결정하게 된다.
$ cd catkin_ws && catkin_make && source devel/setup.bash
$ rosrun oroca_ros_tutorials ros_tutorial_srv_server
위 명령어를 실행하면 서비스 서버가 실행되며 서비스 요청을 대기한다.
$ rosparam list
위 명령어를 치면, 매개변수 목록에 calculation_method가 추가됨을 확인할 수 있다.
그러면 다음 명령어들을 통해서 서비스 서버의 연산을 매개변수를 통해서 바꿀 수 있다.
$ rosservice call /ros_tutorial_srv 10 5
// 15라는 결과값이 나온다.
$ rosparam set /calculation_method 2
$ rosservice call /ros_tutorial_srv 10 5
// 5라는 결과값이 출력된다. 연산이 -로 변경되었다.
$ rosparam set /calculation_method 3
$ rosservice call /ros_tutorial_srv 10 5
// 50이라는 결과값이 출력된다. 연산이 *로 변경되었다.
이런 식으로, 노드 외부에서 노드의 흐름, 설정, 처리 등을 변경시킬 수 있는 유용한 기능이다.