(한 줄로) Pepper를 ROS에 연결할 때의 모범 사례


Pepper를 ROS와 연결하는 방법에 대해서는, 여러가지 시험해 보았습니다만, 지금까지 나중에서 베스트 프랙티스가 되고 있는 방법에 대해서 공유해 둡니다.

환경은
우분투 14.04
ROS Indigo
Choregraphe 2.3

ROS측



갑자기 정답을 말하면 rosbridge의 websocket을 사용합니다. rosbridge는 launch하면 websocket으로 ROS의 Topic을 마음대로 교환해 줍니다. 코드에 손을 추가할 필요가 없습니다! 그래서, 대단한 편. websocket 서버는, 디폴트라고 9090번 포트에 서 있습니다.

launch_rosbridge_server.command
roslaunch rosbridge_server rosbridge_websocket.launch

launch 파일에 기술한다면, 다음의 일행입니다.

chat.launch
<launch>
  <include file="$(find rosbridge_server)/launch/rosbridge_websocket.launch" />
</launch>

Choregraphe 측면



Websocket 클라이언트를 만드는 이유는 ws4py 라이브러리를 사용합니다. Python에서 websocket을 사용하려면 다른 것도 websocket.py라든지 처리의 편한 라이브러리가 있는 것입니다만, ws4py를 선택한 이유는··그냥 GPL회피이기도 합니다.

Choregraphe의 Python에서 추가 라이브러리를 호출하려면 Choregraphe 프로젝트에 추가 한 라이브러리의 디렉토리를 PYTHONPATH에 추가해야합니다. 이 때, 현재의 프로젝트의 디렉토리 위치를 먼저 취득해 둘 필요가 있어 까다롭습니다만, 결과적으로 이하와 같이 됩니다.

add_pythonpath.py
import os, sys
self.framemanager = ALProxy("ALFrameManager")
libdir = os.path.join(self.framemanager.getBehaviorPath(self.behaviorId), "./ws4py")
sys.path.append(libdir)

그리고 나서는, rosbridge가 열고 있는 websocket의 서버에 접속해 메세지(JSON 형식)를 교환할 뿐입니다. 프로토콜에 대해서는 여기을 참조하십시오.
Publish는

publish.js
{ "op": "publish",
  (optional) "id": <string>,
  "topic": <string>,
  "msg": <json>
}

Subscribe는,

subscribe.js
{ "op": "subscribe",
  (optional) "id": <string>,
  "topic": <string>,
  (optional) "type": <string>,
  (optional) "throttle_rate": <int>,
  (optional) "queue_length": <int>,
  (optional) "fragment_size": <int>,
  (optional) "compression": <string>
}

이런 느낌.

클래스에 정리하면,

RosPublisher.py
class RosPublisher(WebSocketClient):
  def __init__(self, sock, topic, mtype, protocols=['http-only', 'chat'], extensions=None, environ=None, heartbeat_freq=None):
    WebSocketClient.__init__(self, sock, protocols, extensions, environ, heartbeat_freq)
      self.topic = topic
      self.mtype = mtype

  def opened(self):
    message = "{\"op\": \"advertise\", " \
               "\"topic\": \"" + self.topic + "\", " \
               "\"type\": \"" + self.mtype + "\"" \
              "}"
    self.send(message)

  def closed(self, code, reason=None):
    message = "{\"op\": \"unadvertise\", " \
               "\"topic\": \"" + self.topic + "\"" \
              "}"
    self.send(message)
    print "Closed down:", code, reason

  def send_message(self, json):
    message = "{\"op\": \"publish\", " \
               "\"topic\": \"" + self.topic + "\", " \
               "\"msg\": " + json + "" \
              "}"
    self.send(message)

RosSubscriber.py
class RosSubscriber(WebSocketClient):
  def __init__(self, sock, topic, mtype, clbk, protocols=['http-only', 'chat'], extensions=None, environ=None, heartbeat_freq=None):
    WebSocketClient.__init__(self, sock, protocols, extensions, environ, heartbeat_freq)
    self.topic = topic
    self.mtype = mtype
    self.callback = clbk

  def opened(self):
    message = "{\"op\": \"subscribe\", " \
               "\"topic\": \"" + self.topic + "\", " \
               "\"type\": \"" + self.mtype + "\"" \
              "}"
    self.send(message)

  def closed(self, code, reason=None):
    message = "{\"op\": \"unsubscribe\", " \
               "\"topic\": \"" + self.topic + "\"" \
              "}"
    self.send(message)
    print "Closed down:", code, reason

  def received_message(self, m):
    self.callback(m)

ROS 주제를 읽고 쓰고 싶은 Choregraphe 상자에서이 녀석을 정의하는 것이 좋습니다. 다른 파일로 시도하면 WebSocketClient의 import 타이밍이 어색합니다. 이 근처 정리한 Choregraphe 프로젝트를 만들었습니다. 그래서 참고로 해 주세요.

부록



자신이 약간 빠진 곳.
  • std_msgs/Bool 일 때의 메시지는 '{"msg": true}'또는 '{"msg": false}'. True 또는 "true"가 아닙니다.
  • std_msgs/String은 받으면 str형이 아니라 unicode형. encode ( 'utf-8')를 사용하여 str 유형으로 수정합니다.
  • 좋은 웹페이지 즐겨찾기