ROS Publisher 및 ROS Subscriber를 사용해 데이터 교환하기
이 예제에서는 ROS 네트워크에서 토픽을 퍼블리시하고 서브스크라이브하는 방법을 보여줍니다.
ROS 노드가 데이터를 교환하는 기본 메커니즘은 메시지를 주고받는 것입니다. 메시지는 토픽으로 전송되며 각 토픽은 ROS 네트워크에서 고유한 이름을 갖습니다. 정보를 공유하려는 노드는 publisher를 사용하여 데이터를 토픽으로 보냅니다. 해당 정보를 수신하려는 노드는 동일한 토픽에 대해 subscriber를 사용합니다. 각 토픽은 고유한 이름을 가질 뿐만 아니라 해당 토픽에서 전송할 수 있는 메시지 유형을 결정하는 메시지 유형도 가집니다.
publisher와 subscriber의 통신에는 다음과 같은 특성이 있습니다.
토픽은 다대다 통신에 사용됩니다. 다수의 publisher가 메시지를 동일한 토픽에 보낼 수 있으며 다수의 subscriber가 메시지를 수신할 수 있습니다.
publisher와 subscriber는 토픽을 사이에 두고 분리되어 있으며 임의의 순서로 생성되고 소멸될 수 있습니다. 활성 subscriber가 없더라도 메시지를 토픽에 퍼블리시할 수 있습니다.
다음 그림은 토픽, publisher, subscriber의 개념을 설명하고 있습니다.
ROS 네트워크에서 토픽을 퍼블리시하고 서브스크라이브하는 방법 외에도, 이 예제에서는 다음을 수행하는 방법을 보여줍니다.
새 메시지가 수신될 때까지 대기하기
콜백을 사용하여 백그라운드에서 새 메시지 처리하기
서브스크라이브하고 메시지 대기하기
rosinit
명령을 사용하여 MATLAB®에서 ROS master를 시작합니다.
rosinit
Launching ROS Core... ...Done in 3.6961 seconds. Initializing ROS master on http://172.19.136.75:56426. Initializing global node /matlab_global_node_67357 with NodeURI http://vdi-wd1bgl-223:60706/ and MasterURI http://localhost:56426.
제공된 헬퍼 함수 exampleHelperROSCreateSampleNetwork
를 사용하여 여러 publisher 및 subscriber가 있는 샘플 ROS 네트워크를 만듭니다.
exampleHelperROSCreateSampleNetwork
rostopic
list
를 사용하여 사용 가능한 토픽을 확인합니다.
rostopic list
/pose /rosout /scan /tf
rostopic info
를 사용하여 /scan
토픽에 퍼블리시 중인 노드가 있는지 확인합니다. 아래의 명령은 node_3
이 퍼블리시 중임을 나타냅니다.
rostopic info /scan
Type: sensor_msgs/LaserScan Publishers: * /node_3 (http://vdi-wd1bgl-223:60722/) Subscribers: * /node_1 (http://vdi-wd1bgl-223:60711/) * /node_2 (http://vdi-wd1bgl-223:60717/)
rossubscriber
를 사용하여 /scan
토픽을 서브스크라이브합니다. (여기에서와 같이) 토픽이 이미 ROS 네트워크에 존재하는 경우 rossubscriber
가 해당 메시지 유형을 자동으로 감지하므로 지정할 필요가 없습니다. 효율성을 높이기 위해 구조체 형식의 메시지를 사용합니다.
laser = rossubscriber("/scan","DataFormat","struct"); pause(2)
receive
를 사용하여 새 메시지를 기다립니다. (두 번째 인수는 초 단위의 시간 제한입니다.) 출력 scandata
에는 수신된 메시지 데이터가 포함됩니다.
scandata = receive(laser,10)
scandata = struct with fields:
MessageType: 'sensor_msgs/LaserScan'
Header: [1×1 struct]
AngleMin: -0.5467
AngleMax: 0.5467
AngleIncrement: 0.0017
TimeIncrement: 0
ScanTime: 0.0330
RangeMin: 0.4500
RangeMax: 10
Ranges: [640×1 single]
Intensities: []
일부 메시지 유형에는 연결된 시각화가 있습니다. LaserScan 메시지의 경우 rosPlot
이 스캔 데이터를 플로팅합니다. MaximumRange
이름-값 쌍은 최대 플롯 범위를 지정합니다.
figure
rosPlot(scandata,"MaximumRange",7)
콜백 함수를 사용하여 서브스크라이브하기
receive
를 사용하여 데이터를 가져오는 대신 새 메시지가 수신될 때 호출될 함수를 지정할 수 있습니다. 이렇게 하면 subscriber가 새 메시지를 기다리는 동안 다른 MATLAB 코드를 실행할 수 있습니다. 여러 subscriber를 사용하려면 콜백이 필수입니다.
콜백 함수 exampleHelperROSPoseCallback
을 사용하여 /pose
토픽을 서브스크라이브합니다.
robotpose = rossubscriber("/pose",@exampleHelperROSPoseCallback,"DataFormat","struct")
robotpose = Subscriber with properties: TopicName: '/pose' LatestMessage: [] MessageType: 'geometry_msgs/Twist' BufferSize: 1 MessagePreprocessingEnabled: 0 NewMessageFcn: @exampleHelperROSPoseCallback DataFormat: 'struct'
기본 작업 공간과 콜백 함수 간에 데이터를 공유하는 한 가지 방법은 전역 변수를 사용하는 것입니다. 두 전역 변수, pos
와 orient
를 정의합니다.
global pos global orient
새로운 메시지 데이터가 /pose
토픽에서 수신되면 전역 변수 pos
와 orient
가 exampleHelperROSPoseCallback
함수에 할당됩니다.
subscriber가 메시지를 받을 수 있도록 몇 초 동안 기다립니다. 최신 위치 데이터와 방향 데이터는 항상 pos
변수와 orient
변수에 저장됩니다.
pause(2) pos
pos = 1×3
0.0429 0.0230 -0.0011
orient
orient = 1×3
0.0079 -0.0263 -0.0041
명령줄에 pos
와 orient
를 몇 번 입력해 보면 해당 값이 계속 업데이트되는 것을 볼 수 있습니다.
subscriber 변수를 지워서 pose subscriber를 중지합니다.
clear robotpose
참고: 전역 변수를 사용하는 것 외에, 콜백 함수에서 정보를 추출하는 다른 방법도 있습니다. 예를 들어 핸들 객체를 추가 인수로 콜백 함수에 전달할 수 있습니다. 콜백 함수 정의에 대한 자세한 내용은 그래픽스 객체에 대한 콜백 만들기 문서를 참조하십시오.
메시지 퍼블리시하기
ROS string형 메시지를 /chatter
토픽으로 보내는 publisher를 만듭니다(Work with Basic ROS Messages 항목 참조).
chatterpub = rospublisher("/chatter","std_msgs/String","DataFormat","struct")
chatterpub = Publisher with properties: TopicName: '/chatter' NumSubscribers: 0 IsLatching: 1 MessageType: 'std_msgs/String' DataFormat: 'struct'
pause(2) % Wait to ensure publisher is registered
/chatter
토픽으로 보낼 ROS 메시지를 만들고 채웁니다.
chattermsg = rosmessage(chatterpub);
chattermsg.Data = 'hello world'
chattermsg = struct with fields:
MessageType: 'std_msgs/String'
Data: 'hello world'
rostopic list
를 사용하여 /chatter
토픽을 ROS 네트워크에서 사용할 수 있는지 확인합니다.
rostopic list
/chatter /pose /rosout /scan /tf
/chatter
토픽의 subscriber를 정의합니다. 새 메시지가 수신되면 exampleHelperROSChatterCallback
이 호출되고 메시지의 문자열 내용이 표시됩니다.
chattersub = rossubscriber("/chatter",@exampleHelperROSChatterCallback,"DataFormat","struct")
chattersub = Subscriber with properties: TopicName: '/chatter' LatestMessage: [] MessageType: 'std_msgs/String' BufferSize: 1 MessagePreprocessingEnabled: 0 NewMessageFcn: @exampleHelperROSChatterCallback DataFormat: 'struct'
/chatter
토픽에 메시지를 퍼블리시합니다. 해당 문자열이 subscriber 콜백에 의해 표시됩니다.
send(chatterpub,chattermsg) pause(2)
ans = 'hello world'
exampleHelperROSChatterCallback
함수는 string형 메시지를 퍼블리시하는 순간 바로 호출되었습니다.
ROS 네트워크 종료하기
ROS 네트워크에서 샘플 노드, publisher, subscriber를 제거합니다. 전역 변수 pos
와 orient.
를 지웁니다.
exampleHelperROSShutDownSampleNetwork clear global pos orient
ROS master를 종료하고 전역 노드를 삭제합니다.
rosshutdown;