diff --git a/ur5_driver/driver.py b/ur5_driver/driver.py
index 0e9d798658fb02dd8fd36ee6fb7f788c3b54bfbc..e3983e32cf9329347063a9187ff895413aa62659 100755
--- a/ur5_driver/driver.py
+++ b/ur5_driver/driver.py
@@ -1,6 +1,7 @@
 #!/usr/bin/env python
 import roslib; roslib.load_manifest('ur5_driver')
 import time, sys, threading, math
+import copy
 import datetime
 import socket
 import struct
@@ -10,7 +11,7 @@ import rospy
 import actionlib
 from sensor_msgs.msg import JointState
 from control_msgs.msg import FollowJointTrajectoryAction
-from trajectory_msgs.msg import JointTrajectoryPoint
+from trajectory_msgs.msg import JointTrajectory, JointTrajectoryPoint
 
 HOSTNAME='ur-xx'
 HOSTNAME="10.0.1.20"
@@ -159,6 +160,10 @@ class CommanderTCPHandler(SocketServer.BaseRequestHandler):
 
     def set_waypoint_finished_cb(self, cb):
         self.waypoint_finished_cb = cb
+
+    # Returns the last JointState message sent out
+    def get_joint_states(self):
+        return self.last_joint_states
     
 
 class TCPServer(SocketServer.TCPServer):
@@ -194,6 +199,39 @@ def reorder_traj_joints(traj, joint_names):
     traj.joint_names = joint_names
     traj.points = new_points
 
+def interp_cubic(p0, p1, t_abs):
+    T = (p1.time_from_start - p0.time_from_start).to_sec()
+    t = t_abs - p0.time_from_start.to_sec()
+    q = [0] * 6
+    qdot = [0] * 6
+    qddot = [0] * 6
+    for i in range(len(p0.positions)):
+        a = p0.positions[i]
+        b = p0.velocities[i]
+        c = (-3*p0.positions[i] + 3*p1.positions[i] - 2*T*p0.velocities[i] - T*p1.velocities[i]) / T**2
+        d = (2*p0.positions[i] - 2*p1.positions[i] + T*p0.velocities[i] + T*p1.velocities[i]) / T**3
+
+        q[i] = a + b*t + c*t**2 + d*t**3
+        qdot[i] = b + 2*c*t + 3*d*t**2
+        qddot[i] = 2*c + 6*d*t
+    return JointTrajectoryPoint(q, qdot, qddot, rospy.Duration(t_abs))
+
+# Returns (q, qdot, qddot) for sampling the JointTrajectory at time t.
+# The time t is the time since the trajectory was started.
+def sample_traj(traj, t):
+    # First point
+    if t <= 0.0:
+        return copy.deepcopy(traj.points[0])
+    # Last point
+    if t >= traj.points[-1].time_from_start.to_sec():
+        return copy.deepcopy(traj.points[-1])
+    
+    # Finds the (middle) segment containing t
+    i = 0
+    while traj.points[i+1].time_from_start.to_sec() < t:
+        i += 1
+    return interp_cubic(traj.points[i], traj.points[i+1], t)
+
 MAX_BLEND = 0.1
 # Determines a blend for the given point that doesn't overlap with its neighbors.
 def compute_blend(traj, index):
@@ -215,7 +253,7 @@ def compute_blend(traj, index):
     return min_diff
 
 class UR5TrajectoryFollower(object):
-    RATE = 0.01
+    RATE = 0.02
     def __init__(self, robot):
         self.following_lock = threading.Lock()
         self.T0 = time.time()
@@ -226,14 +264,31 @@ class UR5TrajectoryFollower(object):
         self.robot.set_waypoint_finished_cb(self.on_waypoint_finished)
 
         self.goal_handle = None
+        self.traj = None
+        self.traj_t0 = 0.0
         self.first_waypoint_id = 10
         self.tracking_i = 0
         self.pending_i = 0
-        self.goal_start_time = rospy.Time(0)
 
         self.update_timer = rospy.Timer(rospy.Duration(self.RATE), self._update)
 
+    def init_traj_from_robot(self):
+        # Busy wait (avoids another mutex)
+        state = self.robot.get_joint_states()
+        while not state:
+            time.sleep(0.1)
+            state = self.robot.get_joint_states()
+        self.traj_t0 = time.time()
+        self.traj = JointTrajectory()
+        self.traj.joint_names = JOINT_NAMES
+        self.traj.points = [JointTrajectoryPoint(
+            positions = state.position,
+            velocities = [0] * 6,
+            accelerations = [0] * 6,
+            time_from_start = rospy.Duration(0.0))]
+
     def start(self):
+        self.init_traj_from_robot()
         self.server.start()
 
     def on_goal(self, goal_handle):
@@ -256,44 +311,66 @@ class UR5TrajectoryFollower(object):
                 self.first_waypoint_id += len(self.goal_handle.get_goal().trajectory.points)
                 self.goal_handle = None
 
-            self.goal_handle = goal_handle
-            self.tracking_i = 0
-            self.pending_i = 0
-            self.goal_start_time = rospy.get_rostime()
+            # Inserts the current setpoint at the head of the trajectory
+            now = time.time()
+            point0 = sample_traj(self.traj, now)
+            point0.time_from_start = rospy.Duration(0.0)
+            goal_handle.get_goal().trajectory.points.insert(0, point0)
+            self.traj_t0 = now
 
-            # Sends a tracking point and a pending point to the robot
+            # Replaces the goal
+            self.goal_handle = goal_handle
+            self.traj = goal_handle.get_goal().trajectory
             self.goal_handle.set_accepted()
-            traj = self.goal_handle.get_goal().trajectory
-            self.robot.send_movej(self.first_waypoint_id, traj.points[0].positions,
-                                  t=get_segment_duration(traj, 0))
-            self.robot.send_movej(self.first_waypoint_id + 1, traj.points[1].positions,
-                                  t=get_segment_duration(traj, 1),
-                                  r=compute_blend(traj, 1))
-            self.tracking_i = 0
-            self.pending_i = 1
+
+            print "New trajectory:"
+            print self.traj
 
     def on_cancel(self, goal_handle):
         log("on_cancel")
         if goal_handle == self.goal_handle:
             with self.following_lock:
-                self.robot.send_stopj()
+                # Uses the next 100ms of trajectory to slow to a stop
+                STOP_DURATION = 0.5
+                now = time.time()
+                point0 = sample_traj(self.traj, now - self.traj_t0)
+                point0.time_from_start = rospy.Duration(0.0)
+                point1 = sample_traj(self.traj, now - self.traj_t0 + STOP_DURATION)
+                point1.velocities = [0] * 6
+                point1.accelerations = [0] * 6
+                point1.time_from_start = rospy.Duration(STOP_DURATION)
+                self.traj_t0 = now
+                self.traj = JointTrajectory()
+                self.traj.joint_names = JOINT_NAMES
+                self.traj.points = [point0, point1]
+                
                 self.goal_handle.set_canceled()
-                self.first_waypoint_id += len(self.goal_handle.get_goal().trajectory.points)
                 self.goal_handle = None
         else:
             goal_handle.set_canceled()
 
     def _update(self, event):
-        t = time.time() - self.T0
-        q = Q2[:]
-        q[0] = Q2[0] + 0.2 * math.sin(0.25 * t*(2*math.pi))
-        q[1] = Q2[1] - 0.2 + 0.2 * math.cos(0.25 * t*(2*math.pi))
-        self.robot.send_servoj(999, q, 0.016)
+        #t = time.time() - self.T0
+        #q = Q2[:]
+        #q[0] = Q2[0] + 0.2 * math.sin(0.25 * t*(2*math.pi))
+        #q[1] = Q2[1] - 0.2 + 0.2 * math.cos(0.25 * t*(2*math.pi))
+        #self.robot.send_servoj(999, q, 0.016)
+
+        if self.traj:
+            now = time.time()
+            if (now - self.traj_t0) <= self.traj.points[-1].time_from_start.to_sec():
+                setpoint = sample_traj(self.traj, now - self.traj_t0)
+                self.robot.send_servoj(999, setpoint.positions, 2 * self.RATE)
+            else:  # Off the end
+                if self.goal_handle:
+                    self.goal_handle.set_succeeded()
+                    self.goal_handle = None
 
 
     # The URScript program sends back waypoint_finished messages,
     # which trigger this callback.
     def on_waypoint_finished(self, waypoint_id):
+        return
         with self.following_lock:
             log("Waypoint finished: %i" % waypoint_id)
             if not self.goal_handle:
diff --git a/ur5_driver/prog b/ur5_driver/prog
index 2a0fe9896227de5cbf104129916bceb05523980c..92bac4849dee0c86ce4578a756a35f265f263c2e 100644
--- a/ur5_driver/prog
+++ b/ur5_driver/prog
@@ -106,7 +106,7 @@ def driverProg():
         servoj(q, 0, 0, dt)
         #send_out("Servoed")
       else:
-        send_out("Idle")
+        #send_out("Idle")
         sync()
       end
     end