개념 설명
Zetabot 로봇 내에서는 ROS(Robot Operating System)를 사용하여 로봇을 제어하고 통신합니다.
ROS 내에서 Topic과 Node가 무엇인지, 해당 Topic을 노드로 게시하고 구독하는 방법을 살펴보았다면 일반적인 ROS Command Line과 Service Server 및 Client 상호 작용을 살펴보겠습니다.
ROS Command Line
1. rosnode command line 도구
rosnode 는 ROS 노드에 대한 정보를 표시할 수 있는 명령입니다. 도구에 지원되는 명령어가 몇 가지 존재합니다.
rosnode info: 노드에 대한 정보를 인쇄합니다. 예시로rosnode info /node_name는 게시 와 구독 을 포함하여 노드에 대한 정보를 표시합니다.rosnode kill: 실행 중인 노드를 종료합니다. 리스폰 되도록 설정된 노드는 죽지 않거나 다시 나타나기 때문에 주의가 필요합니다.노드 이름으로 하나 이상의 노드를 종료합니다.
$ rosnode kill rosout add_two_ints_server add_threeints_server ...
사용자 입력으로 노드 종료 (대화형 모드):
$ rosnode kill 1. /rosout Please enter the number of the node you wish to kill. >
모든 노드를 종료합니다.
kill -a, kill --all
rosnode list: 활성 노드 나열현재 노드 목록을 표시합니다.
$ rosnode list
/namespace_topic 내의 모든 현재 목록을 표시합니다.
$ rosnode list /example_topic_name
XML -RPC URI를 표시하려면 다음을 수행하세요.
$ rosnode list -u
모든 현재 노드(
-a또는--all)의 이름과 XML -RPC UIR를 표시하려면$ rosnode list -a
rosnode machine: 특정 머신에서 실행 중인 노드를 나열하거나 머신을 나열합니다. 예를 들어 Zetabot에서 실행 중인 노드를 보려면 다음을 수행하세요.$ rosnode machine zetabot.local /talker-zetabot.local-72266-1257921234733 /rosout /listener-zetabot.local-72615-1257921238320
rosnode The rostopic command-line tool displays information about ROS topics. Currently, it can display a list of active topics, the publishers and subscribers of a specific topic, the publishing rate of a topic, the bandwidth of a topic, and messages published to a topic. The display of messages is configurable to output in a plotting-friendly format.ping: 반복적으로 핑을 보내 노드에 대한 연결을 테스트합니다.rosnode ping /node_name또는rosnode ping --all를 이용하여 노드 이름을 지정하거나 모든 노드를 ping 하여 개별적으로 또는 전체적으로 노드를 ping 할 수 있습니다.개별 노드를 Count 횟수만큼 ping 할 수도 있습니다.
$ rosnode ping -c 4 rosout rosnode: node is [/rosnode] pinging /rosout with a timeout of 3.0s xmlrpc reply from http://ann:46635/ time=1.195908ms xmlrpc reply from http://ann:46635/ time=1.123905ms xmlrpc reply from http://ann:46635/ time=1.144886ms xmlrpc reply from http://ann:46635/ time=1.137018ms ping average: 1.150429ms
rosnode clearnup: 도달할 수 없는 노드의 등록 정보를 제거합니다. 이 기능은 ROS 노드 표시를 위한 미용 솔루션으로 추가된 기능이므로 기능적 수단으로 사용해서는 안 됩니다.
단순히 지연으로 인해 작동 중인 노드가 종료될 수도 있기 때문입니다.
2. rostopic command line 도구
rostopic 명령줄 도구는 ROS Topic에 대한 정보를 표시합니다. 현재는 활성 토픽 목록, 특정 토픽의 게시자 및 구독자, 토픽 게시 속도, 토픽 대역폭, 토픽에 게시된 메시지를 표시할 수 있습니다. 메시지 표시는 플로팅에 적합한 형식으로 출력되도록 구성할 수 있습니다.
rostopic list모든 현재 토픽을 표시합니다.특정 토픽에 대한 정보를 얻으려면
rostopic list /topic_name명령어를 사용하세요. 이는 ``rostopic info `` 명령과 동일합니다.bag file에 토픽 리스트를 저장하려면
-b인수를 추가하세요.해당 토픽의 게시자만 나열하려면
-p인수를 추가하세요.해당 토픽의 구독자만 나열하려면
-s인수를 추가하세요.-v인수를 추가하여 디스플레이 출력을 제어할 수도 있습니다.
rostopic echo은 토픽에 전송된 메시지를 표시합니다.원하는 토픽을 지정하려면 명령줄 뒤에 토픽 이름을 추가하세요.
$ rostopic echo /imu
3. pm2 command line 도구
pm2 는 시스템 내 애플리케이션 및 노드 관리를 돕는 데몬 프로세스 관리자입니다. 애플리케이션의 경우 다음을 입력할 수 있습니다.
$ pm2 list
ROS Service
우리가 배운 대로 Publish / Subscribe 모델은 매우 유연한 통신 패러다임이지만 요청 / 응답 기반 상호 작용을 어용하지 않습니다. 이에 대한 큰 예는 감지된 모든 정보를 게시하는 대신 피드백 정보를 수신하고 보내야 하는 센서입니다. 우리는 한 쌍의 메시지로 정의된 서비스를 사용하여 요청 / 응답 기반 통신 시스템을 구현할 수 있습니다. 하나는 요청용이고 다른 하나는 응답용입니다.
ROS를 제공하는 노드는 문자열 이름으로 서비스를 제공하고, 클라이언트는 요청 메시지를 보내고 응답을 기다리는 방식으로 서비스를 호출합니다.
앞서 언급했듯이 ROS 서비스는 srv(Simplified Service Description Language) 파일로 정의됩니다. rospy(python 라이브러리)를 사용하면 srv 파일을 Python 소스 코드로 변환하고 ROS 서비스에 필요한 세 가지 클래스를 생성할 수 있습니다.
서비스 정의. 예: (my_package/srv/Foo.srv -> my_package.srv.Foo)
Python 파일 내에서 서비스는 요청 및 응답 유형에 대한 컨테이너로 정의됩니다. 서비스를 생성하거나 호출할 때마다 사용해야 합니다.
add_two_ints = rospy.ServiceProxy('service_name', my_package.srv.Foo)
Request Messages. 예: (my_package/srv/Foo.srv -> my_package.srv.FooRequest)
요쳥 메시지는 적절한 서비스를 호출하는 데 사용됩니다.
Response Messages. 예: (my_package/srv/Foo.srv -> my_package.srv.FooResponse)
응답 메시지는 해당 서비스의 반환 값을 포함하는 데 사용됩니다. 따라서 서비스 핸들러는 올바른 유형의 응답 메시지 인스턴스를 반환해야 합니다.
1. Service proxies
대부분의 경우 rospy.wait_for_service('service_name', timeout=None) 를 이용하여 서비스를 사용할 수 있을 때까지 차단하도록 설정하려고 합니다.
서비스를 사용하려면 rospy.ServiceProxy(name, service_class, persistent=False, headers=None) 사용하여 호출하려는 서비스 이름으로 서비스를 생성해야 합니다.
서비스는 오류를 반환할 수 있으며, 이 경우 예외 처리기가 필요합니다.
rospy.wait_for_service('add_two_ints')
try:
add_two_ints = rospy.ServiceProxy('add_two_ints', AddTwoInts)
resp1 = add_two_ints(x, y)
return resp1.sum
except rospy.ServiceException as e:
print("Service call failed: %s"%e)
2. Calling services
인스턴스 rospy.ServiceProxy 는 호출 가능합니다. Python 환경 내에서는 메소드가 호출되는 방식과 유사하게 이러한 인스턴스를 호출할 수 있습니다.
add_two_ints = rospy.ServiceProxy('add_two_ints', AddTwoInts)
add_two_ints(1, 2)
ServiceProxy 인스턴스에 인수를 전달하는 방법에는 총 세 가지가 있습니다.
명시적 스타일:
명시적 스타일을 사용하면 원 요청 인스턴스를 제작하고 이를 전달하여 게시할 수 있습니다.
request = rospy_tutorials.srv.AddTwoIntsRequest(1, 2) response = add_two_ints(request)
순서대로 인수를 사용하는 암시적 스타일:
순차 스타일에서는 제공된 인수를 순서대로 사용하여 새 Message 인스턴스가 생성됩니다. 이 스타일을 사용하면 모든 필드를 제공해야 합니다.
resp = add_two_ints(1, 2)
키워드 인수를 사용한 암시적 스타일:
키워드 스타일에서는 메시지로 삽입하려는 필드만 초기화할 수 있습니다.
resp = add_two_ints(a = 1)
위의 코드는 a를 1로 설정하고 b를 기본값으로 설정합니다(우리의 경우에는 0입니다).
3. Providing Services
rospy에서는 서비스를 제공하기 위해 새 요청이 수신될 때 호출할 callback이 있는 rospy.Service 인스턴스가 생성됩니다. 각 인바운드 요청은 자체 스레드에서 처리되므로 서비스는 스레드로부터 안전 해야 합니다 .
rospy.Service(name, service_class, handler, buff_size=65536)
새 ROS Service 생성을 위해서는
지정된 이름
서비스 유형
핸들러
핸들러는 서비스 요청과 함께 호출되며 적절한 서비스 응답 메시지를 호출해야 합니다.
def add_two_ints(req): return rospy_tutorials.srv.AddTowIntsResponse(req.a + req.b) def add_two_ints_server(): rospy.init_node('add_two_ints_server') s = rospy.Service('add_two_ints', rospy_tutorials.srv.AddTwoInts, add_two_ints) rospy.spin()
핸들러 반환 유형은 다음과 같습니다.
없음(실패)
서비스 응답
튜플 또는 리스트
딕셔너리
단일 인수 응답만 해당: 필드 값