rosbridge.py
Go to the documentation of this file.
00001 import websocket
00002 import thread
00003 
00004 import json
00005 import traceback
00006 import time
00007 
00008 import string
00009 import random
00010 
00011 
00012 class RosbridgeSetup():
00013     def __init__(self, host, port):
00014         self.callbacks = {}
00015         self.service_callbacks = {}
00016         self.resp = None
00017         self.connection = RosbridgeWSConnection(host, port)
00018         self.connection.registerCallback(self.onMessageReceived)
00019 
00020     def publish(self, topic, obj):
00021         pub = {"op": "publish", "topic": topic, "msg": obj}
00022         self.send(pub)
00023 
00024     def subscribe(self, topic, callback, throttle_rate=-1):
00025         if self.addCallback(topic, callback):
00026             sub = {"op": "subscribe", "topic": topic}
00027             if throttle_rate > 0:
00028                 sub['throttle_rate'] = throttle_rate
00029 
00030             self.send(sub)
00031 
00032     def unhook(self, callback):
00033         keys_for_deletion = []
00034         for key, values in self.callbacks.iteritems():
00035             for value in values:
00036                 if callback == value:
00037                     print "Found!"
00038                     values.remove(value)
00039                     if len(values) == 0:
00040                         keys_for_deletion.append(key)
00041 
00042         for key in keys_for_deletion:
00043             self.unsubscribe(key)
00044             self.callbacks.pop(key)
00045 
00046     def unsubscribe(self, topic):
00047         unsub = {"op": "unsubscribe", "topic": topic}
00048         self.send(unsub)
00049 
00050     def callService(self, serviceName, callback=None, msg=None):
00051         id = self.generate_id()
00052         call = {"op": "call_service", "id": id, "service": serviceName}
00053         if msg != None:
00054             call['args'] = msg
00055 
00056         if callback == None:
00057             self.resp = None
00058             def internalCB(msg):
00059                 self.resp = msg
00060                 return None
00061 
00062             self.addServiceCallback(id, internalCB)
00063             self.send(call)
00064 
00065             while self.resp == None:
00066                 time.sleep(0.01)
00067 
00068             return self.resp
00069 
00070         self.addServiceCallback(id, callback)
00071         self.send(call)
00072         return None
00073 
00074     def send(self, obj):
00075         try:
00076             self.connection.sendString(json.dumps(obj))
00077         except:
00078             traceback.print_exc()
00079             raise
00080 
00081     def generate_id(self, chars=16):
00082         return ''.join(random.SystemRandom().choice(string.ascii_letters + string.digits) for _ in range(chars))
00083 
00084     def addServiceCallback(self, id, callback):
00085         self.service_callbacks[id] = callback
00086 
00087     def addCallback(self, topic, callback):
00088         if self.callbacks.has_key(topic):
00089             self.callbacks[topic].append(callback)
00090             return False
00091 
00092         self.callbacks[topic] = [callback]
00093         return True
00094 
00095     def is_connected(self):
00096         return self.connection.connected
00097 
00098     def is_errored(self):
00099         return self.connection.errored
00100 
00101     def onMessageReceived(self, message):
00102         try:
00103             # Load the string into a JSON object
00104             obj = json.loads(message)
00105             # print "Received: ", obj
00106 
00107             if obj.has_key('op'):
00108                 option = obj['op']
00109                 if option == "publish": # A message from a topic we have subscribed to..
00110                     topic = obj["topic"]
00111                     msg = obj["msg"]
00112                     if self.callbacks.has_key(topic):
00113                         for callback in self.callbacks[topic]:
00114                             try:
00115                                 callback(msg)
00116                             except:
00117                                 print "exception on callback", callback, "from", topic
00118                                 traceback.print_exc()
00119                                 raise
00120                 elif option == "service_response":
00121                     if obj.has_key("id"):
00122                         id = obj["id"]
00123                         values = obj["values"]
00124                         if self.service_callbacks.has_key(id):
00125                             try:
00126                                 #print 'id:', id, 'func:', self.service_callbacks[id]
00127                                 self.service_callbacks[id](values)
00128                             except:
00129                                 print "exception on callback ID:", id
00130                                 traceback.print_exc()
00131                                 raise
00132                     else:
00133                         print "Missing ID!"
00134                 else:
00135                     print "Recieved unknown option - it was: ", option
00136             else:
00137                 print "No OP key!"
00138         except:
00139             print "exception in onMessageReceived"
00140             print "message", message
00141             traceback.print_exc()
00142             raise
00143 
00144 
00145 class RosbridgeWSConnection():
00146     def __init__(self, host, port):
00147         self.ws = websocket.WebSocketApp(("ws://%s:%d/" % (host, port)), on_message=self.on_message, on_error=self.on_error, on_close=self.on_close)
00148         self.ws.on_open = self.on_open
00149         self.run_thread = thread.start_new_thread(self.run, ())
00150         self.connected = False
00151         self.errored = False
00152         self.callbacks = []
00153 
00154     def on_open(self, ws):
00155         print "### ROS bridge connected ###"
00156         self.connected=True
00157 
00158     def sendString(self, message):
00159         if not self.connected:
00160             print "Error: not connected, could not send message"
00161             # TODO: throw exception
00162         else:
00163             self.ws.send(message)
00164 
00165     def on_error(self, ws, error):
00166         self.errored = True
00167         print "Error: %s" % error
00168 
00169     def on_close(self, ws):
00170         self.connected = False
00171         print "### ROS bridge closed ###"
00172 
00173     def run(self, *args):
00174         self.ws.run_forever()
00175 
00176     def on_message(self, ws, message):
00177         # Call the handlers
00178         for callback in self.callbacks:
00179             callback(message)
00180 
00181     def registerCallback(self, callback):
00182         self.callbacks.append(callback)


mir_driver
Author(s): Martin Günther
autogenerated on Wed May 8 2019 02:53:33