diff --git a/ur_driver/prog b/ur_driver/prog
index 2f0aff8c1b30d442bf8c30d64f237887e7efbf5a..de63229e2a067155451ec9b20215863494fbcc5c 100644
--- a/ur_driver/prog
+++ b/ur_driver/prog
@@ -20,6 +20,7 @@ def driverProg():
   MULT_jointstate = 10000.0
   MULT_time = 1000000.0
   MULT_blend = 1000.0
+  MULT_analog = 1000000.0
   pi = 3.14159265359
   
   def send_out(msg):
@@ -36,61 +37,7 @@ def driverProg():
     socket_send_int(waypoint_id)
     exit_critical
   end
-  
-  thread statePublisherThread():
-    def send_joint_state():
-      q = get_joint_positions()
-      qdot = get_joint_speeds()
-      tau = get_joint_torques()
-      wrench = get_tcp_force()
-      enter_critical
-      socket_send_int(MSG_JOINT_STATES)
-      socket_send_int(floor(MULT_jointstate * q[0]))
-      socket_send_int(floor(MULT_jointstate * q[1]))
-      socket_send_int(floor(MULT_jointstate * q[2]))
-      socket_send_int(floor(MULT_jointstate * q[3]))
-      socket_send_int(floor(MULT_jointstate * q[4]))
-      socket_send_int(floor(MULT_jointstate * q[5]))
-      socket_send_int(floor(MULT_jointstate * qdot[0]))
-      socket_send_int(floor(MULT_jointstate * qdot[1]))
-      socket_send_int(floor(MULT_jointstate * qdot[2]))
-      socket_send_int(floor(MULT_jointstate * qdot[3]))
-      socket_send_int(floor(MULT_jointstate * qdot[4]))
-      socket_send_int(floor(MULT_jointstate * qdot[5]))
-      socket_send_int(floor(MULT_jointstate * tau[0]))
-      socket_send_int(floor(MULT_jointstate * tau[1]))
-      socket_send_int(floor(MULT_jointstate * tau[2]))
-      socket_send_int(floor(MULT_jointstate * tau[3]))
-      socket_send_int(floor(MULT_jointstate * tau[4]))
-      socket_send_int(floor(MULT_jointstate * tau[5]))
-      socket_send_int(MSG_WRENCH)
-      socket_send_int(floor(MULT_wrench * wrench[0]))
-      socket_send_int(floor(MULT_wrench * wrench[1]))
-      socket_send_int(floor(MULT_wrench * wrench[2]))
-      socket_send_int(floor(MULT_wrench * wrench[3]))
-      socket_send_int(floor(MULT_wrench * wrench[4]))
-      socket_send_int(floor(MULT_wrench * wrench[5]))
-      socket_send_int(MSG_GET_IO)
-      socket_send_int(1*get_digital_in(0) + 2*get_digital_in(1) + 4 * get_digital_in(2) + 8 * get_digital_in(3) + 16 * get_digital_in(4) + 32 * get_digital_in(5) + 64 * get_digital_in(6) + 128 * get_digital_in(7) + 256 * get_digital_in(8) + 512 * get_digital_in(9))
-      socket_send_int(1*get_digital_out(0) + 2*get_digital_out(1) + 4 * get_digital_out(2) + 8 * get_digital_out(3) + 16 * get_digital_out(4) + 32 * get_digital_out(5) + 64 * get_digital_out(6) + 128 * get_digital_out(7) + 256 * get_digital_out(8) + 512 * get_digital_out(9))
-      socket_send_int(pow(2,0)*get_flag(0) + pow(2,1)*get_flag(1) + pow(2,2)*get_flag(2) + pow(2,3)*get_flag(3) + pow(2,4)*get_flag(4) + pow(2,5)*get_flag(5) + pow(2,6)*get_flag(6) + pow(2,7)*get_flag(7) + pow(2,8)*get_flag(8) + pow(2,9)*get_flag(9) + pow(2,10)*get_flag(10) + pow(2,11)*get_flag(11) + pow(2,12)*get_flag(12) + pow(2,13)*get_flag(13) + pow(2,14)*get_flag(14) + pow(2,15)*get_flag(15) + pow(2,16)*get_flag(16) + pow(2,17)*get_flag(17) + pow(2,18)*get_flag(18) + pow(2,19)*get_flag(19) + pow(2,20)*get_flag(20) + pow(2,21)*get_flag(21) + pow(2,22)*get_flag(22) + pow(2,23)*get_flag(23) + pow(2,24)*get_flag(24) + pow(2,25)*get_flag(25) + pow(2,26)*get_flag(26) + pow(2,27)*get_flag(27) + pow(2,28)*get_flag(28) + pow(2,29)*get_flag(29) + pow(2,30)*get_flag(30) + pow(2,31)*get_flag(31))
-      socket_send_int(get_analog_out(0)*1000000)
-      socket_send_int(get_analog_out(1)*1000000)
-      socket_send_int(get_analog_in(0)*1000000)
-      socket_send_int(get_analog_in(1)*1000000)
-      socket_send_int(get_analog_in(2)*1000000)
-      socket_send_int(get_analog_in(3)*1000000)
-      #socket_send_int(7895160)  # Recognizable  ".xxx" or 00787878
-      exit_critical
-    end
-    #socket_open(HOSTNAME, 50002)
-    send_joint_state()
-    while True:
-      send_joint_state()
-      sync()
-    end
-    sync()
-  end
+
   
   SERVO_IDLE = 0
   SERVO_RUNNING = 1
@@ -143,7 +90,6 @@ def driverProg():
   socket_open(HOSTNAME, PORT)
   send_out("hello")
   
-  thread_state = run statePublisherThread()
   thread_servo = run servoThread()
   
   # Servoes in a circle
@@ -235,41 +181,41 @@ def driverProg():
       elif mtype == MSG_SET_DIGITAL_OUT:
         #send_out("Received Digital Out Signal")
         # Reads the parameters
-        params_mult = socket_read_binary_integer(1+6+1)
+        params_mult = socket_read_binary_integer(2)
         if params_mult[0] == 0:
-          send_out("Received no parameters for set_out message")
+          send_out("Received no parameters for set_digital_out message")
         end
         if params_mult[2] > 0:
-      set_digital_out(params_mult[1], True)
+           set_digital_out(params_mult[1], True)
         elif params_mult[2] == 0:
           set_digital_out(params_mult[1], False)
         end
       elif mtype == MSG_SET_FLAG:
         #send_out("Received Set Flag Signal")
         # Reads the parameters
-        params_mult = socket_read_binary_integer(1+6+1)
+        params_mult = socket_read_binary_integer(2)
         if params_mult[0] == 0:
-          send_out("Received no parameters for set_out message")
+          send_out("Received no parameters for set_flag message")
         end
         if params_mult[2] != 0:
-      set_flag(params_mult[1], True)
+          set_flag(params_mult[1], True)
         elif params_mult[2] == 0:
           set_flag(params_mult[1], False)
         end
       elif mtype == MSG_SET_ANALOG_OUT:
         #send_out("Received Analog Out Signal")
         # Reads the parameters
-        params_mult = socket_read_binary_integer(1+6+1)
+        params_mult = socket_read_binary_integer(2)
         if params_mult[0] == 0:
-          send_out("Received no parameters for set_out message")
+          send_out("Received no parameters for set_analog_out message")
         end
-        set_analog_out(params_mult[1], (params_mult[2] / 1000000))
+        set_analog_out(params_mult[1], (params_mult[2] / MULT_analog))
       elif mtype == MSG_SET_TOOL_VOLTAGE:
         #send_out("Received Tool Voltage Signal")
-        # Reads the parameters
-        params_mult = socket_read_binary_integer(1+6+1)
+        # Reads the parameters (also reads second dummy '0' integer)
+        params_mult = socket_read_binary_integer(2)
         if params_mult[0] == 0:
-          send_out("Received no parameters for set_out message")
+          send_out("Received no parameters for set_tool_voltage message")
         end
         set_tool_voltage(params_mult[1])
       else:
@@ -278,8 +224,6 @@ def driverProg():
     end
   end
   
-  #sleep(1)
-  kill thread_state
   socket_send_int(MSG_QUIT)
 end
 driverProg()
diff --git a/ur_driver/src/ur_driver/deserializeRT.py b/ur_driver/src/ur_driver/deserializeRT.py
new file mode 100644
index 0000000000000000000000000000000000000000..5fe97d779d67613fa47eb55d44668b228a66bb68
--- /dev/null
+++ b/ur_driver/src/ur_driver/deserializeRT.py
@@ -0,0 +1,118 @@
+import struct
+import copy
+
+class RobotStateRT(object):
+    __slots__ = ['time', 
+                 'q_target', 'qd_target', 'qdd_target', 'i_target', 'm_target', 
+                 'q_actual', 'qd_actual', 'i_actual', 'tool_acc_values', 
+                 'unused', 
+                 'tcp_force', 'tool_vector', 'tcp_speed', 
+                 'digital_input_bits', 'motor_temperatures', 'controller_timer', 
+                 'test_value', 
+                 'robot_mode', 'joint_modes']
+
+    @staticmethod
+    def unpack(buf):
+        offset = 0
+        message_size = struct.unpack_from("!i", buf, offset)[0]
+        offset+=4
+        if message_size != len(buf):
+            print("MessageSize: ", message_size, "; BufferSize: ", len(buf))
+            raise Exception("Could not unpack RobotStateRT packet: length field is incorrect")
+
+        rs = RobotStateRT()
+        #time: 1x double (1x 8byte)
+        rs.time = struct.unpack_from("!d",buf, offset)[0]
+        offset+=8
+        
+        #q_target: 6x double (6x 8byte)
+        all_values = list(struct.unpack_from("!dddddd",buf, offset))
+        offset+=6*8
+        rs.q_target = copy.deepcopy(all_values)
+        
+        #qd_target: 6x double (6x 8byte)
+        all_values = list(struct.unpack_from("!dddddd",buf, offset))
+        offset+=6*8
+        rs.qd_target = copy.deepcopy(all_values)
+        
+        #qdd_target: 6x double (6x 8byte)
+        all_values = list(struct.unpack_from("!dddddd",buf, offset))
+        offset+=6*8
+        rs.qdd_target = copy.deepcopy(all_values)
+        
+        #i_target: 6x double (6x 8byte) 
+        all_values = list(struct.unpack_from("!dddddd",buf, offset))
+        offset+=6*8
+        rs.i_target = copy.deepcopy(all_values)
+        
+        #m_target: 6x double (6x 8byte)
+        all_values = list(struct.unpack_from("!dddddd",buf, offset))
+        offset+=6*8
+        rs.m_target = copy.deepcopy(all_values)
+        
+        #q_actual: 6x double (6x 8byte)
+        all_values = list(struct.unpack_from("!dddddd",buf, offset))
+        offset+=6*8
+        rs.q_actual = copy.deepcopy(all_values)
+        
+        #qd_actual: 6x double (6x 8byte)
+        all_values = list(struct.unpack_from("!dddddd",buf, offset))
+        offset+=6*8
+        rs.qd_actual = copy.deepcopy(all_values)
+        
+        #i_actual: 6x double (6x 8byte)
+        all_values = list(struct.unpack_from("!dddddd",buf, offset))
+        offset+=6*8
+        rs.i_actual = copy.deepcopy(all_values)
+        
+        #tool_acc_values: 3x double (3x 8byte)
+        all_values = list(struct.unpack_from("!ddd",buf, offset))
+        offset+=3*8
+        rs.tool_acc_values = copy.deepcopy(all_values)
+        
+        #unused: 15x double (15x 8byte)
+        offset+=120
+        rs.unused = []
+        
+        #tcp_force: 6x double (6x 8byte)
+        all_values = list(struct.unpack_from("!dddddd",buf, offset))
+        offset+=6*8
+        rs.tcp_force = copy.deepcopy(all_values)
+        
+        #tool_vector: 6x double (6x 8byte)
+        all_values = list(struct.unpack_from("!dddddd",buf, offset))
+        offset+=6*8
+        rs.tool_vector = copy.deepcopy(all_values)
+        
+        #tcp_speed: 6x double (6x 8byte)
+        all_values = list(struct.unpack_from("!dddddd",buf, offset))
+        offset+=6*8
+        rs.tcp_speed = copy.deepcopy(all_values)
+        
+        #digital_input_bits: 1x double (1x 8byte) ?
+        rs.digital_input_bits = struct.unpack_from("!d",buf, offset)[0]
+        offset+=8
+
+        #motor_temperatures: 6x double (6x 8byte)
+        all_values = list(struct.unpack_from("!dddddd",buf, offset))
+        offset+=6*8
+        rs.motor_temperatures = copy.deepcopy(all_values)
+        
+        #controller_timer: 1x double (1x 8byte)
+        rs.controller_timer = struct.unpack_from("!d",buf, offset)[0]
+        offset+=8
+        
+        #test_value: 1x double (1x 8byte)
+        rs.test_value = struct.unpack_from("!d",buf, offset)[0]
+        offset+=8
+        
+        #robot_mode: 1x double (1x 8byte)
+        rs.robot_mode = struct.unpack_from("!d",buf, offset)[0]
+        offset+=8
+        
+        #joint_mode: 6x double (6x 8byte)
+        all_values = list(struct.unpack_from("!dddddd",buf, offset))
+        offset+=6*8
+        rs.joint_modes = copy.deepcopy(all_values)
+
+        return rs
diff --git a/ur_driver/src/ur_driver/driver.py b/ur_driver/src/ur_driver/driver.py
index 5588801bedec5633f15a433cf49280a4c06e885e..469e523d2220eb89424f1787ca9e377ff5cab29d 100755
--- a/ur_driver/src/ur_driver/driver.py
+++ b/ur_driver/src/ur_driver/driver.py
@@ -17,6 +17,7 @@ from trajectory_msgs.msg import JointTrajectory, JointTrajectoryPoint
 from geometry_msgs.msg import WrenchStamped
 
 from ur_driver.deserialize import RobotState, RobotMode
+from ur_driver.deserializeRT import RobotStateRT
 
 from ur_msgs.srv import SetPayload, SetIO
 from ur_msgs.msg import *
@@ -35,8 +36,9 @@ prevent_programming = False
 # q_actual = q_from_driver + offset
 joint_offsets = {}
 
-PORT=30002
-DEFAULT_REVERSE_PORT = 50001
+PORT=30002       # 10 Hz, RobotState 
+RT_PORT=30003    #125 Hz, RobotStateRT
+DEFAULT_REVERSE_PORT = 50001     #125 Hz, custom data (from prog)
 
 MSG_OUT = 1
 MSG_QUIT = 2
@@ -57,6 +59,8 @@ MULT_wrench = 10000.0
 MULT_jointstate = 10000.0
 MULT_time = 1000000.0
 MULT_blend = 1000.0
+MULT_analog = 1000000.0
+MULT_analog_robotstate = 0.1
 
 #Bounds for SetPayload service
 MIN_PAYLOAD = 0.0
@@ -82,6 +86,8 @@ Q3 = [1.5,-0.2,-1.57,0,0,0]
 connected_robot = None
 connected_robot_lock = threading.Lock()
 connected_robot_cond = threading.Condition(connected_robot_lock)
+last_joint_states = None
+last_joint_states_lock = threading.Lock()
 pub_joint_states = rospy.Publisher('joint_states', JointState)
 pub_wrench = rospy.Publisher('wrench', WrenchStamped)
 pub_io_states = rospy.Publisher('io_states', IOStates)
@@ -185,22 +191,40 @@ class URConnection(object):
             rospy.logfatal("Real robot is no longer enabled.  Driver is fuxored")
             time.sleep(2)
             sys.exit(1)
-
-        # If the urscript program is not executing, then the driver
-        # needs to publish joint states using information from the
-        # robot state packet.
-        if self.robot_state != self.EXECUTING:
-            msg = JointState()
-            msg.header.stamp = rospy.get_rostime()
-            msg.header.frame_id = "From binary state data"
-            msg.name = joint_names
-            msg.position = [0.0] * 6
-            for i, jd in enumerate(state.joint_data):
-                msg.position[i] = jd.q_actual + joint_offsets.get(joint_names[i], 0.0)
-            msg.velocity = [jd.qd_actual for jd in state.joint_data]
-            msg.effort = [0]*6
-            pub_joint_states.publish(msg)
-            self.last_joint_states = msg
+        
+        ###
+        # IO-Support is EXPERIMENTAL
+        # 
+        # Notes: 
+        # - Where are the flags coming from? Do we need flags? No, as 'prog' does not use them and other scripts are not running!
+        # - analog_input2 and analog_input3 are within ToolData
+        # - What to do with the different analog_input/output_range/domain?
+        # - Shall we have appropriate ur_msgs definitions in order to reflect MasterboardData, ToolData,...?
+        ###
+        
+        # Use information from the robot state packet to publish IOStates        
+        msg = IOStates()
+        #gets digital in states
+        for i in range(0, 10):
+            msg.digital_in_states.append(DigitalIn(i, (state.masterboard_data.digital_input_bits & (1<<i))>>i))
+        #gets digital out states
+        for i in range(0, 10):
+            msg.digital_out_states.append(DigitalOut(i, (state.masterboard_data.digital_output_bits & (1<<i))>>i))
+        #gets analog_in[0] state
+        inp = state.masterboard_data.analog_input0 / MULT_analog_robotstate
+        msg.analog_in_states.append(Analog(0, inp))
+        #gets analog_in[1] state
+        inp = state.masterboard_data.analog_input1 / MULT_analog_robotstate
+        msg.analog_in_states.append(Analog(1, inp))      
+        #gets analog_out[0] state
+        inp = state.masterboard_data.analog_output0 / MULT_analog_robotstate
+        msg.analog_out_states.append(Analog(0, inp))     
+        #gets analog_out[1] state
+        inp = state.masterboard_data.analog_output1 / MULT_analog_robotstate
+        msg.analog_out_states.append(Analog(1, inp))     
+        #print "Publish IO-Data from robot state data"
+        pub_io_states.publish(msg)
+        
 
         # Updates the state machine that determines whether we can program the robot.
         can_execute = (state.robot_mode_data.robot_mode in [RobotMode.READY, RobotMode.RUNNING])
@@ -238,11 +262,114 @@ class URConnection(object):
                 if more:
                     self.__buf = self.__buf + more
 
-                    # Attempts to extract a packet
-                    packet_length, ptype = struct.unpack_from("!IB", self.__buf)
-                    if len(self.__buf) >= packet_length:
-                        packet, self.__buf = self.__buf[:packet_length], self.__buf[packet_length:]
-                        self.__on_packet(packet)
+                    #unpack_from requires a buffer of at least 48 bytes
+                    while len(self.__buf) >= 48:
+                        # Attempts to extract a packet
+                        packet_length, ptype = struct.unpack_from("!IB", self.__buf)
+                        #print("PacketLength: ", packet_length, "; BufferSize: ", len(self.__buf))
+                        if len(self.__buf) >= packet_length:
+                            packet, self.__buf = self.__buf[:packet_length], self.__buf[packet_length:]
+                            self.__on_packet(packet)
+                        else:
+                            break
+
+                else:
+                    self.__trigger_disconnected()
+                    self.__keep_running = False
+                    
+            else:
+                self.__trigger_disconnected()
+                self.__keep_running = False
+
+
+class URConnectionRT(object):
+    TIMEOUT = 1.0
+    
+    DISCONNECTED = 0
+    CONNECTED = 1
+    
+    def __init__(self, hostname, port):
+        self.__thread = None
+        self.__sock = None
+        self.robot_state = self.DISCONNECTED
+        self.hostname = hostname
+        self.port = port
+        self.last_stateRT = None
+
+    def connect(self):
+        if self.__sock:
+            self.disconnect()
+        self.__buf = ""
+        self.robot_state = self.CONNECTED
+        self.__sock = socket.create_connection((self.hostname, self.port))
+        self.__keep_running = True
+        self.__thread = threading.Thread(name="URConnectionRT", target=self.__run)
+        self.__thread.daemon = True
+        self.__thread.start()
+        
+    def disconnect(self):
+        if self.__thread:
+            self.__keep_running = False
+            self.__thread.join()
+            self.__thread = None
+        if self.__sock:
+            self.__sock.close()
+            self.__sock = None
+        self.last_state = None
+        self.robot_state = self.DISCONNECTED
+
+    def __trigger_disconnected(self):
+        log("Robot disconnected")
+        self.robot_state = self.DISCONNECTED
+
+    def __on_packet(self, buf):
+        global last_joint_states, last_joint_states_lock
+        now = rospy.get_rostime()
+        stateRT = RobotStateRT.unpack(buf)
+        self.last_stateRT = stateRT
+        
+        msg = JointState()
+        msg.header.stamp = now
+        msg.header.frame_id = "From real-time state data"
+        msg.name = joint_names
+        msg.position = [0.0] * 6
+        for i, q in enumerate(stateRT.q_actual):
+            msg.position[i] = q + joint_offsets.get(joint_names[i], 0.0)
+        msg.velocity = stateRT.qd_actual
+        msg.effort = [0]*6
+        pub_joint_states.publish(msg)
+        with last_joint_states_lock:
+            last_joint_states = msg
+        
+        wrench_msg = WrenchStamped()
+        wrench_msg.header.stamp = now
+        wrench_msg.wrench.force.x = stateRT.tcp_force[0]
+        wrench_msg.wrench.force.y = stateRT.tcp_force[1]
+        wrench_msg.wrench.force.z = stateRT.tcp_force[2]
+        wrench_msg.wrench.torque.x = stateRT.tcp_force[3]
+        wrench_msg.wrench.torque.y = stateRT.tcp_force[4]
+        wrench_msg.wrench.torque.z = stateRT.tcp_force[5]
+        pub_wrench.publish(wrench_msg)
+        
+
+    def __run(self):
+        while self.__keep_running:
+            r, _, _ = select.select([self.__sock], [], [], self.TIMEOUT)
+            if r:
+                more = self.__sock.recv(4096)
+                if more:
+                    self.__buf = self.__buf + more
+                    
+                    #unpack_from requires a buffer of at least 48 bytes
+                    while len(self.__buf) >= 48:
+                        # Attempts to extract a packet
+                        packet_length = struct.unpack_from("!i", self.__buf)[0]
+                        #print("PacketLength: ", packet_length, "; BufferSize: ", len(self.__buf))
+                        if len(self.__buf) >= packet_length:
+                            packet, self.__buf = self.__buf[:packet_length], self.__buf[packet_length:]
+                            self.__on_packet(packet)
+                        else:
+                            break
                 else:
                     self.__trigger_disconnected()
                     self.__keep_running = False
@@ -272,6 +399,7 @@ def getConnectedRobot(wait=False, timeout=-1):
 class CommanderTCPHandler(SocketServer.BaseRequestHandler):
 
     def recv_more(self):
+        global last_joint_states, last_joint_states_lock
         while True:
             r, _, _ = select.select([self.request], [], [], 0.2)
             if r:
@@ -281,15 +409,14 @@ class CommanderTCPHandler(SocketServer.BaseRequestHandler):
                 return more
             else:
                 now = rospy.get_rostime()
-                if self.last_joint_states and \
-                        self.last_joint_states.header.stamp < now - rospy.Duration(1.0):
+                if last_joint_states and \
+                        last_joint_states.header.stamp < now - rospy.Duration(1.0):
                     rospy.logerr("Stopped hearing from robot (last heard %.3f sec ago).  Disconnected" % \
-                                     (now - self.last_joint_states.header.stamp).to_sec())
+                                     (now - last_joint_states.header.stamp).to_sec())
                     raise EOF()
 
     def handle(self):
         self.socket_lock = threading.Lock()
-        self.last_joint_states = None
         setConnectedRobot(self)
         print "Handling a request"
         try:
@@ -314,110 +441,7 @@ class CommanderTCPHandler(SocketServer.BaseRequestHandler):
                             raise Exception("Probably forgot to terminate a string: %s..." % buf[:150])
                     s, buf = buf[:i], buf[i+1:]
                     log("Out: %s" % s)
-
-                elif mtype == MSG_JOINT_STATES:
-                    while len(buf) < 3*(6*4):
-                        buf = buf + self.recv_more()
-                    state_mult = struct.unpack_from("!%ii" % (3*6), buf, 0)
-                    buf = buf[3*6*4:]
-                    state = [s / MULT_jointstate for s in state_mult]
-
-                    msg = JointState()
-                    msg.header.stamp = rospy.get_rostime()
-                    msg.name = joint_names
-                    msg.position = [0.0] * 6
-                    for i, q_meas in enumerate(state[:6]):
-                        msg.position[i] = q_meas + joint_offsets.get(joint_names[i], 0.0)
-                    msg.velocity = state[6:12]
-                    msg.effort = state[12:18]
-                    self.last_joint_states = msg
-                    pub_joint_states.publish(msg)
-
-                elif mtype == MSG_WRENCH:
-                    while len(buf) < (6*4):
-                        buf = buf + self.recv_more()
-                    state_mult = struct.unpack_from("!%ii" % (6), buf, 0)
-                    buf = buf[6*4:]
-                    state = [s / MULT_wrench for s in state_mult]
-                    wrench_msg = WrenchStamped()
-                    wrench_msg.header.stamp = rospy.get_rostime()
-                    wrench_msg.wrench.force.x = state[0]
-                    wrench_msg.wrench.force.y = state[1]
-                    wrench_msg.wrench.force.z = state[2]
-                    wrench_msg.wrench.torque.x = state[3]
-                    wrench_msg.wrench.torque.y = state[4]
-                    wrench_msg.wrench.torque.z = state[5]
-                    pub_wrench.publish(wrench_msg)
-
-                #gets all IO States and publishes them into a message
-                elif mtype == MSG_GET_IO:
-
-                    #gets digital in states
-                    while len(buf) < 4:
-                        buf = buf + self.recv_more()
-                    inp = struct.unpack_from("!i", buf, 0)[0]
-                    buf = buf[4:]
-                    msg = IOStates()
-                    for i in range(0, 10):
-                        msg.digital_in_states.append(DigitalIn(i, (inp & (1<<i))>>i))
-                    #gets digital out states
-                    while len(buf) < 4:
-                        buf = buf + self.recv_more()
-                    inp = struct.unpack_from("!i", buf, 0)[0]
-                    buf = buf[4:]
-                    for i in range(0, 10):
-                        msg.digital_out_states.append(DigitalOut(i, (inp & (1<<i))>>i))
-                    #gets flag states
-                    while len(buf) < 4:
-                        buf = buf + self.recv_more()
-                    inp = struct.unpack_from("!i", buf, 0)[0]
-                    buf = buf[4:]
-                    for i in range(0, 32):
-                        msg.flag_states.append(Flag(i, (inp & (1<<i))>>i))
-                    #gets analog_out[0] state
-                    while len(buf) < 4:
-                        buf = buf + self.recv_more()
-                    inp = struct.unpack_from("!i", buf, 0)[0]
-                    inp /= 1000000.0
-                    buf = buf[4:]
-                    msg.analog_out_states.append(Analog(0, inp))
-                    #gets analog_out[1] state
-                    while len(buf) < 4:
-                        buf = buf + self.recv_more()
-                    inp = struct.unpack_from("!i", buf, 0)[0]
-                    inp /= 1000000.0
-                    buf = buf[4:]
-                    msg.analog_out_states.append(Analog(1, inp))
-                    #gets analog_in[0] state
-                    while len(buf) < 4:
-                        buf = buf + self.recv_more()
-                    inp = struct.unpack_from("!i", buf, 0)[0]
-                    inp /= 1000000.0
-                    buf = buf[4:]
-                    msg.analog_in_states.append(Analog(0, inp))
-                    #gets analog_in[1] state
-                    while len(buf) < 4:
-                        buf = buf + self.recv_more()
-                    inp = struct.unpack_from("!i", buf, 0)[0]
-                    inp /= 1000000.0
-                    buf = buf[4:]
-                    msg.analog_in_states.append(Analog(1, inp))
-                    #gets analog_in[2] state
-                    while len(buf) < 4:
-                        buf = buf + self.recv_more()
-                    inp = struct.unpack_from("!i", buf, 0)[0]
-                    inp /= 1000000.0
-                    buf = buf[4:]
-                    msg.analog_in_states.append(Analog(2, inp))
-                    #gets analog_in[3] state
-                    while len(buf) < 4:
-                        buf = buf + self.recv_more()
-                    inp = struct.unpack_from("!i", buf, 0)[0]
-                    inp /= 1000000.0
-                    buf = buf[4:]
-                    msg.analog_in_states.append(Analog(3, inp))
-                    pub_io_states.publish(msg)
-
+                
                 elif mtype == MSG_QUIT:
                     print "Quitting"
                     raise EOF("Received quit")
@@ -472,7 +496,7 @@ class CommanderTCPHandler(SocketServer.BaseRequestHandler):
     def set_analog_out(self, pinnum, value):
         params = [MSG_SET_ANALOG_OUT] + \
                  [pinnum] + \
-                 [value * 1000000]
+                 [value * MULT_analog]
         buf = struct.pack("!%ii" % len(params), *params)
         #print params
         with self.socket_lock:
@@ -487,7 +511,7 @@ class CommanderTCPHandler(SocketServer.BaseRequestHandler):
         #print params
         with self.socket_lock:
             self.request.send(buf) 
-        time.sleep(IO_SLEEP_TIME+.5)
+        time.sleep(IO_SLEEP_TIME)
 
     def set_flag(self, pin, val):
         params = [MSG_SET_FLAG] + \
@@ -509,7 +533,8 @@ class CommanderTCPHandler(SocketServer.BaseRequestHandler):
 
     # Returns the last JointState message sent out
     def get_joint_states(self):
-        return self.last_joint_states
+        global last_joint_states, last_joint_states_lock
+        return last_joint_states
     
 
 class TCPServer(SocketServer.TCPServer):
@@ -925,6 +950,9 @@ def main():
     connection.connect()
     connection.send_reset_program()
     
+    connectionRT = URConnectionRT(robot_hostname, RT_PORT)
+    connectionRT.connect()
+    
     set_io_server()
     
     service_provider = None
diff --git a/ur_driver/src/ur_driver/io_interface.py b/ur_driver/src/ur_driver/io_interface.py
index a7fa6d7ba65bdb9ac2509fdf4937a9076afbf0de..e78c0b4236aae3c773debffabf4db4ce96e2eb4c 100644
--- a/ur_driver/src/ur_driver/io_interface.py
+++ b/ur_driver/src/ur_driver/io_interface.py
@@ -10,49 +10,50 @@ FUN_SET_FLAG = 2
 FUN_SET_ANALOG_OUT = 3
 FUN_SET_TOOL_VOLTAGE = 4
 
-Flag_States = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
-Digital_Out_States = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
-Digital_In_States = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
-Analog_Out_States = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
-Analog_In_States = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
+#Flag_States = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
+Digital_Out_States = [0,0,0,0,0,0,0,0,0,0]  #8(controller)+2(tool)
+Digital_In_States = [0,0,0,0,0,0,0,0,0,0]   #8(controller)+2(tool)
+Analog_Out_States = [0,0]  #2(controller)
+Analog_In_States = [0,0]   #2(controller)+0(tool)
 
 ANALOG_TOLERANCE_VALUE = 0.01
-DELAY_TIME = 0.3
-i = 0
-set_io = rospy.ServiceProxy('set_io', SetIO)
 
 def set_io_val(fun, pin, val):
-    rospy.wait_for_service('set_io')
     try:
         set_io(fun, pin, val)
     except rospy.ServiceException, e:
         print "Service call failed: %s"%e
 
 def set_tool_voltage(volts):
-    set_io_val(FUN_SET_TOOL_VOLTAGE, volts, 0)
+    try:
+        set_io(FUN_SET_TOOL_VOLTAGE, volts, 0)
+    except rospy.ServiceException, e:
+        print "Service call failed: %s"%e
 
 def set_digital_out(pin, val):
-    set_io_val(FUN_SET_DIGITAL_OUT, pin, val)
-    if Digital_Out_States[pin] != val:
-        rospy.logwarn("DIGITAL OUT IS NOT A HAPPY CAMPER, its not setting a pin on the first try, it may help to increase IO_SLEEP_TIME in driver.py")
-        set_digital_out(pin, val)
+    try:
+        set_io(FUN_SET_DIGITAL_OUT, pin, val)
+    except rospy.ServiceException, e:
+        print "Service call failed: %s"%e
 
 def set_analog_out(pin, val):
-    set_io_val(FUN_SET_ANALOG_OUT, pin, val)
-    if abs(Analog_Out_States[pin] - val) > ANALOG_TOLERANCE_VALUE:
-        rospy.logwarn("ANALOG OUT IS NOT A HAPPY CAMPER, its not setting a pin on the first try, it may help to increase IO_SLEEP_TIME in driver.py")
-        set_digital_out(pin, val)
+    try:
+        set_io(FUN_SET_ANALOG_OUT, pin, val)
+    except rospy.ServiceException, e:
+        print "Service call failed: %s"%e
 
 def set_flag(pin, val):
-    set_io_val(FUN_SET_FLAG, pin, val)
-    if Flag_States[pin] != val:
-        rospy.logwarn("SETTING A FLAG IS NOT A HAPPY CAMPER, its not setting a pin on the first try, it may help to increase IO_SLEEP_TIME in driver.py")
-        set_digital_out(pin, val)
+    rospy.logerr("SETTING FLAGS IS NOT SUPPORTED!")
+    #try:
+        #set_io(FUN_SET_FLAG, pin, val)
+    #except rospy.ServiceException, e:
+        #print "Service call failed: %s"%e
 
 def callback(data):
-    for i in range(0,32):
-        del Flag_States[i]
-        Flag_States.insert(i, data.flag_states[i].state)
+    rospy.logerr("Flag_States are currently not supported")
+    #for i in range(0,32):
+        #del Flag_States[i]
+        #Flag_States.insert(i, data.flag_states[i].state)
     for i in range(0,10):
         del Digital_Out_States[i]
         Digital_Out_States.insert(i, data.digital_out_states[i].state)
@@ -62,11 +63,17 @@ def callback(data):
     for i in range(0,2):
         del Analog_Out_States[i]
         Analog_Out_States.insert(i, data.analog_out_states[i].state)
-    for i in range(0,4):
+    rospy.logerr("ToolInput analog_in[2] and analog_in[3] currently not supported")
+    for i in range(0,2):
         del Analog_In_States[i]
         Analog_In_States.insert(i, data.analog_in_states[i].state)
 
 def get_states():
     rospy.init_node('UR_State_Getter')
     rospy.Subscriber("io_states", IOStates, callback)
+    
+def set_states():
+    rospy.wait_for_service('set_io')
+    global set_io
+    set_io = rospy.ServiceProxy('set_io', SetIO)
 
diff --git a/ur_driver/src/ur_driver/testRT_comm.py b/ur_driver/src/ur_driver/testRT_comm.py
new file mode 100755
index 0000000000000000000000000000000000000000..84c74142a553e2e52ba20584addd4881c593e1ed
--- /dev/null
+++ b/ur_driver/src/ur_driver/testRT_comm.py
@@ -0,0 +1,98 @@
+#!/usr/bin/env python
+import roslib; roslib.load_manifest('ur_driver')
+import time, sys, threading, math
+import copy
+import datetime
+import socket, select
+import struct
+import traceback, code
+import SocketServer
+
+import rospy
+
+from sensor_msgs.msg import JointState
+from ur_driver.deserializeRT import RobotStateRT
+from ur_msgs.msg import *
+
+
+joint_names = ['shoulder_pan_joint', 'shoulder_lift_joint', 'elbow_joint',
+               'wrist_1_joint', 'wrist_2_joint', 'wrist_3_joint']
+joint_offsets = {}
+
+
+def __on_packet(buf):
+    stateRT = RobotStateRT.unpack(buf)
+    
+    msg = RobotStateRTMsg()
+    msg.time = stateRT.time
+    msg.q_target = stateRT.q_target
+    msg.qd_target = stateRT.qd_target
+    msg.qdd_target = stateRT.qdd_target
+    msg.i_target = stateRT.i_target
+    msg.m_target = stateRT.m_target
+    msg.q_actual = stateRT.q_actual
+    msg.qd_actual = stateRT.qd_actual
+    msg.i_actual = stateRT.i_actual
+    msg.tool_acc_values = stateRT.tool_acc_values
+    msg.tcp_force = stateRT.tcp_force
+    msg.tool_vector = stateRT.tool_vector
+    msg.tcp_speed = stateRT.tcp_speed
+    msg.digital_input_bits = stateRT.digital_input_bits
+    msg.motor_temperatures = stateRT.motor_temperatures
+    msg.controller_timer = stateRT.controller_timer
+    msg.test_value = stateRT.test_value
+    msg.robot_mode = stateRT.robot_mode
+    msg.joint_modes = stateRT.joint_modes
+    pub_robot_stateRT.publish(msg)       
+    
+
+    msg = JointState()
+    msg.header.stamp = rospy.get_rostime()
+    msg.header.frame_id = "From real-time state data"
+    msg.name = joint_names
+    msg.position = [0.0] * 6
+    for i, q in enumerate(stateRT.q_actual):
+        msg.position[i] = q + joint_offsets.get(joint_names[i], 0.0)
+    msg.velocity = stateRT.qd_actual
+    msg.effort = [0]*6
+    pub_joint_statesRT.publish(msg)
+
+
+
+
+def main():
+    rospy.init_node('testRT_comm', disable_signals=True)
+    
+    global pub_joint_statesRT
+    pub_joint_statesRT = rospy.Publisher('joint_statesRT', JointState)
+    global pub_robot_stateRT
+    pub_robot_stateRT = rospy.Publisher('robot_stateRT', RobotStateRTMsg)
+    
+    
+    
+    robot_hostname = '192.168.0.42'
+    rt_port = 30003
+    
+    rt_socket = socket.create_connection((robot_hostname, rt_port))
+    buf = ""
+    
+    while not rospy.is_shutdown():
+        more = rt_socket.recv(4096)
+        if more:
+            buf = buf + more
+
+            # Attempts to extract a packet
+            packet_length = struct.unpack_from("!i", buf)[0]
+            print("PacketLength: ", packet_length, "; BufferSize: ", len(buf))
+            if len(buf) >= packet_length:
+                packet, buf = buf[:packet_length], buf[packet_length:]
+                __on_packet(packet)
+        else:
+            print("There is no more...")
+    
+    rt_socket.close()
+
+
+
+
+if __name__ == '__main__': main()
diff --git a/ur_driver/src/ur_driver/test_comm.py b/ur_driver/src/ur_driver/test_comm.py
new file mode 100755
index 0000000000000000000000000000000000000000..29381354ccbf99050666cb8c68a982ce1625c847
--- /dev/null
+++ b/ur_driver/src/ur_driver/test_comm.py
@@ -0,0 +1,120 @@
+#!/usr/bin/env python
+import roslib; roslib.load_manifest('ur_driver')
+import time, sys, threading, math
+import copy
+import datetime
+import socket, select
+import struct
+import traceback, code
+import SocketServer
+
+import rospy
+
+from sensor_msgs.msg import JointState
+from ur_driver.deserialize import RobotState
+from ur_msgs.msg import *
+
+# renaming classes
+DigitalIn = Digital
+DigitalOut = Digital
+Flag  = Digital
+
+MULT_analog = 1000000.0
+MULT_analog_robotstate = 0.1
+
+joint_names = ['shoulder_pan_joint', 'shoulder_lift_joint', 'elbow_joint',
+               'wrist_1_joint', 'wrist_2_joint', 'wrist_3_joint']
+joint_offsets = {}
+
+
+def __on_packet(buf):
+    state = RobotState.unpack(buf)
+    
+    mb_msg = MasterboardDataMsg()
+    mb_msg.digital_input_bits = state.masterboard_data.digital_input_bits
+    mb_msg.digital_output_bits = state.masterboard_data.digital_output_bits
+    mb_msg.analog_input_range0 = state.masterboard_data.analog_input_range0
+    mb_msg.analog_input_range1 = state.masterboard_data.analog_input_range1
+    mb_msg.analog_input0 = state.masterboard_data.analog_input0
+    mb_msg.analog_input1 = state.masterboard_data.analog_input1
+    mb_msg.analog_output_domain0 = state.masterboard_data.analog_output_domain0
+    mb_msg.analog_output_domain1 = state.masterboard_data.analog_output_domain1
+    mb_msg.analog_output0 = state.masterboard_data.analog_output0
+    mb_msg.analog_output1 = state.masterboard_data.analog_output1
+    mb_msg.masterboard_temperature = state.masterboard_data.masterboard_temperature
+    mb_msg.robot_voltage_48V = state.masterboard_data.robot_voltage_48V
+    mb_msg.robot_current = state.masterboard_data.robot_current
+    mb_msg.master_io_current = state.masterboard_data.master_io_current
+    mb_msg.master_safety_state = state.masterboard_data.master_safety_state
+    mb_msg.master_onoff_state = state.masterboard_data.master_onoff_state
+    pub_masterboard_state.publish(mb_msg)
+    
+    
+    # Use information from the robot state packet to publish IOStates        
+    msg = IOStates()
+    #gets digital in states
+    for i in range(0, 10):
+        msg.digital_in_states.append(DigitalIn(i, (state.masterboard_data.digital_input_bits & (1<<i))>>i))
+    #gets digital out states
+    for i in range(0, 10):
+        msg.digital_out_states.append(DigitalOut(i, (state.masterboard_data.digital_output_bits & (1<<i))>>i))
+    #gets analog_in[0] state
+    inp = state.masterboard_data.analog_input0 / MULT_analog_robotstate
+    msg.analog_in_states.append(Analog(0, inp))
+    #gets analog_in[1] state
+    inp = state.masterboard_data.analog_input1 / MULT_analog_robotstate
+    msg.analog_in_states.append(Analog(1, inp))      
+    #gets analog_out[0] state
+    inp = state.masterboard_data.analog_output0 / MULT_analog_robotstate
+    msg.analog_out_states.append(Analog(0, inp))     
+    #gets analog_out[1] state
+    inp = state.masterboard_data.analog_output1 / MULT_analog_robotstate
+    msg.analog_out_states.append(Analog(1, inp))     
+    #print "Publish IO-Data from robot state data"
+    pub_io_states.publish(msg)
+    
+    # Notes: 
+    # - Where are the flags coming from? Do we need flags? No, as 'prog' does not use them and other scripts are not running!
+    # - analog_input2 and analog_input3 are within ToolData
+    # - What to do with the different analog_input/output_range/domain?
+    # - Shall we have appropriate ur_msgs definitions in order to reflect MasterboardData, ToolData,...?
+
+
+
+
+
+def main():
+    rospy.init_node('test_comm', disable_signals=True)
+    
+    global pub_masterboard_state
+    pub_masterboard_state = rospy.Publisher('masterboard_state', MasterboardDataMsg)
+    global pub_io_states
+    pub_io_states = rospy.Publisher('io_states', IOStates)
+    
+    
+    robot_hostname = '192.168.0.42'
+    port = 30002
+    
+    test_socket = socket.create_connection((robot_hostname, port))
+    buf = ""
+    
+    while not rospy.is_shutdown():
+        more = test_socket.recv(4096)
+        if more:
+            buf = buf + more
+
+            # Attempts to extract a packet
+            packet_length = struct.unpack_from("!i", buf)[0]
+            print("PacketLength: ", packet_length, "; BufferSize: ", len(buf))
+            if len(buf) >= packet_length:
+                packet, buf = buf[:packet_length], buf[packet_length:]
+                __on_packet(packet)
+        else:
+            print("There is no more...")
+    
+    test_socket.close()
+
+
+
+
+if __name__ == '__main__': main()
diff --git a/ur_driver/test_io.py b/ur_driver/test_io.py
index 1d62d1703f8026e7d31ae11c20cda9352a45c358..7b3c2a82686bbea6d30a6b8b57becabaf7359fe7 100755
--- a/ur_driver/test_io.py
+++ b/ur_driver/test_io.py
@@ -3,23 +3,27 @@ import time
 from ur_driver.io_interface import *
 
 if __name__ == "__main__":
-    print "toggling things"
+    print "testing io-interface"
     get_states()
     print "listener has been activated"
+    set_states()
+    print "service-server has been started"
     while(True):
         set_tool_voltage(12)
         set_digital_out(0, True)
         set_analog_out(0, 0.75)
-        set_flag(0, True)
-        print(Flag_States[0])
+        #print "Flags are currently not supported"
+        ##set_flag(0, True)
+        ##print(Flag_States[0])
         print(Analog_Out_States[0])
         print(Digital_Out_States[0])
         time.sleep(1)
         set_tool_voltage(24)
         set_digital_out(0, False)
         set_analog_out(0, 0.25)
-        set_flag(0, False)
-        print(Flag_States[0])
+        #print "Flags are currently not supported"
+        ##set_flag(0, False)
+        ##print(Flag_States[0])
         print(Analog_Out_States[0])
         print(Digital_Out_States[0])
         time.sleep(1)
diff --git a/ur_msgs/CMakeLists.txt b/ur_msgs/CMakeLists.txt
index 1fc2dd9b027babcb8db1996ab0de0265aeb45ba5..20c5fef587a121af6f3dc04417662bbad5847b6a 100644
--- a/ur_msgs/CMakeLists.txt
+++ b/ur_msgs/CMakeLists.txt
@@ -13,6 +13,8 @@ find_package(catkin REQUIRED COMPONENTS message_generation std_msgs)
    Analog.msg
    Digital.msg
    IOStates.msg
+   RobotStateRTMsg.msg
+   MasterboardDataMsg.msg
  )
 
 ## Generate services in the 'srv' folder
diff --git a/ur_msgs/msg/MasterboardDataMsg.msg b/ur_msgs/msg/MasterboardDataMsg.msg
new file mode 100644
index 0000000000000000000000000000000000000000..8ccdd6202e4dcd42c51d5efd5e45823961062736
--- /dev/null
+++ b/ur_msgs/msg/MasterboardDataMsg.msg
@@ -0,0 +1,27 @@
+# This data structure contains the MasterboardData structure
+# used by the Universal Robots controller
+#
+# MasterboardData is part of the data structure being send on the 
+# secondary client communications interface
+# 
+# This data structure is send at 10 Hz on TCP port 30002
+# 
+# Dokumentation can be found on the Universal Robots Support Wiki
+# (http://wiki03.lynero.net/Technical/DataStreamFromURController?rev=8)
+
+int16 digital_input_bits
+int16 digital_output_bits
+int8 analog_input_range0
+int8 analog_input_range1
+float64 analog_input0
+float64 analog_input1
+int8 analog_output_domain0
+int8 analog_output_domain1
+float64 analog_output0
+float64 analog_output1
+float32 masterboard_temperature
+float32 robot_voltage_48V
+float32 robot_current
+float32 master_io_current
+uint8 master_safety_state
+uint8 master_onoff_state
diff --git a/ur_msgs/msg/RobotStateRTMsg.msg b/ur_msgs/msg/RobotStateRTMsg.msg
new file mode 100644
index 0000000000000000000000000000000000000000..2741463973e0c1ed1d052f885e274fb912efc860
--- /dev/null
+++ b/ur_msgs/msg/RobotStateRTMsg.msg
@@ -0,0 +1,27 @@
+# Data structure for the realtime communications interface (aka Matlab interface)
+# used by the Universal Robots controller
+# 
+# This data structure is send at 125 Hz on TCP port 30003
+# 
+# Dokumentation can be found on the Universal Robots Support Wiki
+# (http://wiki03.lynero.net/Technical/RealTimeClientInterface?rev=9)
+
+float64 time
+float64[] q_target
+float64[] qd_target
+float64[] qdd_target
+float64[] i_target
+float64[] m_target
+float64[] q_actual
+float64[] qd_actual
+float64[] i_actual
+float64[] tool_acc_values
+float64[] tcp_force
+float64[] tool_vector
+float64[] tcp_speed
+float64 digital_input_bits
+float64[] motor_temperatures
+float64 controller_timer
+float64 test_value
+float64 robot_mode
+float64[] joint_modes