-
_ROS1_package_pub&subROS/ROS1 2023. 10. 2. 14:50
ROS package
package는 ROS에서 개발되는 소프트웨어를 논리적 묶음으로 만듣 것이다.
ROS에서 제공하는 명령어
$ rospack list # ros package 나열 $ rospack find [package_name] # 이름으로 package 검색 $ roscd [location_name[/subdir]] # ROS package dir로 이동 $ rosls [location_name[/subdir]] # Linux ls와 유사 $ rosed [file_name] # (환경 설정에 따른) 에디터로 파일을 편집
위에서 rospack list와 roscd는 정말 자주 사용된다.
Package 만들기
참고 사이트
http://wiki.ros.org/ROS/Tutorials/CreatingPackage
$ cd ~/catkin_ws/src # 패키지를 담을 디렉토리로 이동 $ catkin_create_pkg my_pkg1 std_msgs rospy roscpp # 패키지 이름지정 및 해당 패키지가 의존하는 다른 패키지 나열
패키지가 만들어지면 catkin_make로 빌드를 하자.
제대로 빌드가 되었다면 다음과 같이 나온다.
만들어진 패키지는 다음과 같이 확인한다.
$ rospack find my_pkg1 # my_pkg1의 위치를 알려줌 $ rospack depends1 my_pkg1 # my_pkg1의 종속성을 알려줌 $ roscd my_pkg1 # my_pkg1으로 이동
Publish & Subscribe
이번에는 publish와 subscribe 노드를 만들어서 데이터를 주고 받는지 확인을 해볼 것이다.
코드는 내가 만든 pkg안의 src폴더에 넣으면 된다.
이번 pub과 sub예제는 python으로 만들어졌다.
1. Publish(Python)
pub.py의 코드는 다음과 같다.
#!/usr/bin/env python # 모든 ROS Python노드에 선언됨. 내 스크립트가 파이썬 스크립트로 실행되는 것을 확인 import rospy from geometry_msgs.msg import Twist rospy.init_node('my_node', anonymous=True) # 내 노드 이름 pub = rospy.Publisher('/turtle1/cmd_vel', Twist, queue_size=10) # Publish 객체 생성 msg = Twist() msg.linear.x = 2.0 msg.linear.y = 0.0 msg.linear.z = 0.0 msg.angular.x = 0.0 msg.angular.y = 0.0 msg.angular.z = 1.8 rate = rospy.Rate(1) #Rate 개체 속도. 초당 1번 루트 통과 while not rospy.is_shutdown(): # shutdown 되지 않으면 계속 반복 pub.publish(msg) rate.sleep() #루프 호출 속도. 루프가 원하는 rate를 유지할 수 있게 해줌.
작성한 Python 코드를 사용하려면 실행 권한을 줘야한다. 초기에는 실행권한이 없으므로 chmod 명령어로 권한을 부여해야한다.
이전에 실습했던 turtle_teleop_key 대신 pub.py를 사용하면 다음의 결과를 볼 수 있다.
2. Subscribe(Python)
이번에는 publish를 받는 subscribe노드를 만들어 볼 것이다.
sub.py의 코드는 다음과 같다.
#!/usr/bin/env python import rospy from turtlesim.msg import Pose def callback(data): s = "Location: %.2f, %.2f" % (data.x, data.y) rospy.loginfo(rospy.get_caller_id() + s) rospy.init_node("my_listener", anonymous=True) # 노드의 고유한 이름 부여 rospy.Subscriber("/turtle1/pose", Pose, callback) # 메시지를 수신하고 콜백 호출 rospy.spin() # while과 같은 역할. 반복
마찬가지로 chmod +x를 사용하여 권한을 부여한다.
실행하면 다음과 같이 sub.py에서 거북이 로봇의 위치를 가져오는 것을 볼 수 있다.
3. Publish & Subscribe(C++)
이번에는 C++을 사용하여 예제를 실습해보려고 한다.
참고 사이트
http://wiki.ros.org/ROS/Tutorials/WritingPublisherSubscriber%28c%2B%2B%29
일단 talker와 listener라는 두 가지 패키지를 작성한다. 이는 main이 두번 정의되지 않게 하기 위함이다.
talker 패키지에 작성하며 talker.cpp코드는 다음과 같다.
#include "ros/ros.h" #include "std_msgs/String.h" #include <sstream> int main(int argc, char **argv) { ros::init(argc, argv, "talker"); //노드 초기화 및 고유한 이름 부여 ros::NodeHandle n; // 노드 핸들 생성. 노드 핸들은 노드의 초기화 수행 및 파괴시 리소스 정리 //마스터에 chatter에 대한 std_msgs/String 유형의 메시지를 게시할 것이라고 전달. 최대 1000개의 메시지. ros::Publisher chatter_pub = n.advertise<std_msgs::String>("chatter", 1000); // 루프를 수행할 주파수 지정. 마지막에 sleep 호출 후 올바른 시간동안 절전을 할 수 있게 해줌. ros::Rate loop_rate(10); int count = 0; while (ros::ok()) // false를 반환할 때까지 반복 { std_msgs::String msg; std::stringstream ss; ss << "hello world " << count; msg.data = ss.str(); ROS_INFO("%s", msg.data.c_str()); chatter_pub.publish(msg); //연결된 노드에 메시지 전송 ros::spinOnce(); loop_rate.sleep(); // 메시지를 전달하고 남은 시간동안 절전. ++count; } return 0; }
listener.cpp 코드는 다음과 같다.
#include "ros/ros.h" #include "std_msgs/String.h" // 새로운 메시지가 도착했을 때 호출되는 콜백함수 void chatterCallback(const std_msgs::String::ConstPtr& msg) { ROS_INFO("I heard: [%s]", msg->data.c_str()); } int main(int argc, char **argv) { ros::init(argc, argv, "listener"); // 노드 고유 이름 설정 ros::NodeHandle n; //1000개의 메시지를 받음.(1000개에 도달하면 이전 메시지는 버림) ros::Subscriber sub = n.subscribe("chatter", 1000, chatterCallback); ros::spin(); return 0; }
이번에는 빌드를 하기 위해서 package.xml과 CMakeList.txt 파일을 조금 수정해야 한다.
해당 파일 수정은 위의 사이트의 3. Building your nodes 부분을 참고하면 된다.
- CMakeList.txt
우리는 talker.cpp와 listener.cpp를 빌드해야 하므로 add_executable, target_link_libraries, add_dependencies에 다음 과 같이 내용을 추가해야 한다.(Ctrl + f로 찾아서 하거나 복붙을 추천)
add_executable(talker src/talker.cpp) target_link_libraries(talker ${catkin_LIBRARIES}) add_dependencies(talker beginner_tutorials_generate_messages_cpp) add_executable(listener src/listener.cpp) target_link_libraries(listener ${catkin_LIBRARIES}) add_dependencies(listener beginner_tutorials_generate_messages_cpp)
cpp로 작성한 파일은 굳이 권한을 주지 않아도 작동한다.
두 프로그램을 실행해보면 다음과 같은 모습을 볼 수 있다.
명령어:
# Terminal 1 $ roscore # Terminal 2 $ rosrun talker talker # Terminal 3 $ rosrun listener listener
'ROS > ROS1' 카테고리의 다른 글
_ROS1_node_communication (0) 2023.10.04 _ROS1_roslaunch (0) 2023.10.03 _ROS1_설치_환경설정_기본실습 (0) 2023.10.01 _ROS1_기본 내용 (1) 2023.10.01 _ROS1_Robot Operating System (0) 2023.09.27