학습 내용
메시지를 통한 노드 간 통신
Teacher(Publisher)가 "my_topic"이라는 토픽을 Student(Subscriber)에게 전송하면 Student가 이 화면에 출력하는 토픽 통신 시스템을 구현해 보자. 언어는 C++를 사용한다.
디렉터리 구성은 다음과 같다.
xycar_ws
├─ build
├─ devel
└─ src
├─ CMakeLists.txt
└─ msg_send
├─ CMakeLists.txt
├─ launch
│ └─ m_send.launch
└─ src
├─ teacher.cpp
└─ student.cpp
먼저 msg_send 패키지를 ROS workspace인 xycar_ws의 src 폴더 안에 생성하여야 한다. 이때 catkin_create_pkg을 사용하여 패키지를 생성할 수 있고 msg_send 패키지는 std_msgs와 roscpp를 depend한다.
// catkin_create_pkg [pkgname] [depend1] [depend2]
$ cd ~/xycar_ws/src
$ catkin_create_pkg msg_send roscpp std_msgs
다음으로 Launch 디렉터리를 만들어주고 새로 만든 패키지를 빌드한다.
// msg_send 폴더 내부에 생성
$ mkdir launch
$ cm
이제 msg_send/src에 토픽을 발행하고 구독하는 C++ 코드를 작성하면 된다. 토픽 이름은 "my_topic"이며 Publisher인 teacher.cpp에서 "call me please"를 담아서 전송한다. 이후 Subscriber인 student.cpp에서 토픽을 받아 내용을 화면에 출력한다. msg_src로 이동하여 gedit을 사용해서 코드를 작성한다.
$ gedit teacher.cpp
$ gedit student.cpp
teacher.cpp
#include <ros/ros.h>
#include <std_msgs/String.h>
int main(int argc, char **argv) {
ros::init(argc, argv, "teacher", ros::init_options::AnonymousName);
ros::NodeHandle nh;
ros::Publisher pub = nh.advertise<std_msgs::String>("my_topic", 10);
ros::Rate rate(2); // 발행 속도를 설정 (2 Hz로 설정).
while (ros::ok()) {
std_msgs::String msg;
msg.data = "call me please";
pub.publish(msg);
rate.sleep();
}
return 0;
}
student.cpp
#include <ros/ros.h>
#include <std_msgs/String.h>
void callback(const std_msgs::String::ConstPtr& msg) {
ROS_INFO("%s", msg->data.c_str());
}
int main(int argc, char **argv) {
ros::init(argc, argv, "student", ros::init_options::AnonymousName);
ros::NodeHandle nh;
ros::Subscriber sub = nh.subscribe("my_topic", 10, callback);
ros::spin();
return 0;
}
이때 반드시 msg_send 내부의 CMakeLists.txt에 아래와 같은 조건들을 추가해줘야 한다.
# CMarkLists.txt 내부에 추가하면 된다
add_executable(teacher src/teacher.cpp)
add_executable(student src/student.cpp)
add_dependencies(teacher ${catkin_EXPORTED_TARGETS})
add_dependencies(student ${catkin_EXPORTED_TARGETS})
install(TARGETS teacher
RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)
install(TARGETS student
RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)
# 아래에 나온 부분들도 혹시 주석처리가 되어있다면 해제한다
find_package(catkin REQUIRED COMPONENTS
roscpp
std_msgs
)
catkin_package(
INCLUDE_DIRS include
LIBRARIES msg_send
CATKIN_DEPENDS roscpp std_msgs
DEPENDS system_lib
)
include_directories(
include
${catkin_INCLUDE_DIRS}
)
* 만약 add_executable([node name] [source file])이나 install(TARGETS ~)의 node 이름, 주소가 제대로 설정되지 않으면 빌드, rosrun, roslaunch 시 에러가 발생할 수 있다. 실행 권한을 부여하였음에도 'cannot launch node of type ~' 에러가 발생한다면 이 부분을 확인해 보자.
이제 launch 파일을 작성하자. msg_send/launch로 이동하여 gedit을 통해 launch 파일을 작성한다. 파일을 작성한 후 cm을 통해 빌드한다.
// 위치는 msg_send/launch 아래이다
$ gedit m_send.launch
// txt 파일 내부에 아래와 같이 작성한다
<launch>
<node pkg="msg_send" type="teacher" name="teacher_node">
</node>
<node pkg="msg_send" type="student" name="student_node" output="screen">
</node>
</launch>
// 이후 다시 빌드한다
$ cm
이후 rosrun이나 roslaunch에서 에러가 발생할 수도 있기 때문에 빌드 후 터미널을 종료하고 새 터미널에서 작업하는 것을 추천한다. 또한 ' [rosrun] Couldn't find executable named ~'와 같은 에러가 발생한다면 아래와 같이 현재 빌드를 삭제하고 새롭게 빌드하면 문제를 해결할 수 있다.
$ cd ~/xycar_ws
$ rm -rf build devel
$ cm
chmod +x를 사용하여 각 소스파일에 실행권한을 부여해야 한다.
$ chmod +x ~/xycar_ws/src/msg_send/src/teacher.cpp
$ chmod +x ~/xycar_ws/src/msg_send/src/student.cpp
모든 설정이 끝났으므로 launch 파일을 실행하여 결과를 확인한다.
// 이때 다른 터미널에서 roscore가 실행되고 있어야한다
$ roslaunch msg_send m_send.launch
다음과 같이 화면에 call me please가 성공적으로 출력되는 것을 확인할 수 있다.
CMake 사용 시 참고하면 좋은 자료 : https://gist.github.com/dongbum/d1d49e38a20f9cf52ea39f9ce2702160
CMake 할때 쪼오오금 도움이 되는 문서
CMake 할때 쪼오오금 도움이 되는 문서. GitHub Gist: instantly share code, notes, and snippets.
gist.github.com
'Study > ROS' 카테고리의 다른 글
[ROS 튜토리얼] 과제 #1. 누락 없이 모두 잘 도착하는가? (0) | 2023.10.03 |
---|---|
[ROS 튜토리얼] ROS 통신 중 발생하는 다양한 문제 상황과 해결 방법 (1) | 2023.10.03 |
[ROS 튜토리얼] ROS 기초 실습 (1) 거북이 토픽 전송 (0) | 2023.09.25 |
[ROS 튜토리얼] ROS 설치 방법 (0) | 2023.09.25 |
[ROS 튜토리얼] ROS 기초 (0) | 2023.09.25 |