35 from __future__
import division
38 __author__ =
'Antons Rebguns' 39 __copyright__ =
'Copyright (c) 2010-2011 Antons Rebguns' 42 __maintainer__ =
'Antons Rebguns' 43 __email__ =
'anton@email.arizona.edu' 46 from threading
import Thread
51 from std_msgs.msg
import Float64
52 from trajectory_msgs.msg
import JointTrajectory
53 from control_msgs.msg
import FollowJointTrajectoryAction
54 from control_msgs.msg
import FollowJointTrajectoryFeedback
55 from control_msgs.msg
import FollowJointTrajectoryResult
66 def __init__(self, controller_namespace, controllers):
85 if c.port_namespace
in self.
port_to_io:
continue 101 self.goal_constraints.append(rospy.get_param(ns +
'/' + joint +
'/goal', -1.0))
102 self.trajectory_constraints.append(rospy.get_param(ns +
'/' + joint +
'/trajectory', -1.0))
105 self.
msg = FollowJointTrajectoryFeedback()
107 self.msg.desired.positions = [0.0] * self.
num_joints 108 self.msg.desired.velocities = [0.0] * self.
num_joints 109 self.msg.desired.accelerations = [0.0] * self.
num_joints 110 self.msg.actual.positions = [0.0] * self.
num_joints 111 self.msg.actual.velocities = [0.0] * self.
num_joints 112 self.msg.error.positions = [0.0] * self.
num_joints 113 self.msg.error.velocities = [0.0] * self.
num_joints 124 FollowJointTrajectoryAction,
127 self.action_server.start()
134 if self.action_server.is_active(): self.action_server.set_preempted()
136 while self.action_server.is_active():
145 num_points = len(traj.points)
149 res = FollowJointTrajectoryResult()
150 res.error_code=FollowJointTrajectoryResult.INVALID_JOINTS
151 msg =
'Incoming trajectory joints do not match the joints of the controller' 153 rospy.logerr(
' self.joint_names={%s}' % (set(self.
joint_names)))
154 rospy.logerr(
' traj.joint_names={%s}' % (set(traj.joint_names)))
155 self.action_server.set_aborted(result=res, text=msg)
160 msg =
'Incoming trajectory is empty' 162 self.action_server.set_aborted(text=msg)
167 lookup = [traj.joint_names.index(joint)
for joint
in self.
joint_names]
168 durations = [0.0] * num_points
171 durations[0] = traj.points[0].time_from_start.to_sec()
173 for i
in range(1, num_points):
174 durations[i] = (traj.points[i].time_from_start - traj.points[i - 1].time_from_start).to_sec()
176 if not traj.points[0].positions:
177 res = FollowJointTrajectoryResult()
178 res.error_code=FollowJointTrajectoryResult.INVALID_GOAL
179 msg =
'First point of trajectory has no positions' 181 self.action_server.set_aborted(result=res, text=msg)
185 time = rospy.Time.now() + rospy.Duration(0.01)
187 for i
in range(num_points):
190 if traj.header.stamp == rospy.Time(0.0):
191 seg.start_time = (time + traj.points[i].time_from_start).to_sec() - durations[i]
193 seg.start_time = (traj.header.stamp + traj.points[i].time_from_start).to_sec() - durations[i]
195 seg.duration = durations[i]
198 if traj.points[i].velocities
and len(traj.points[i].velocities) != self.
num_joints:
199 res = FollowJointTrajectoryResult()
200 res.error_code=FollowJointTrajectoryResult.INVALID_GOAL
201 msg =
'Command point %d has %d elements for the velocities' % (i, len(traj.points[i].velocities))
203 self.action_server.set_aborted(result=res, text=msg)
206 if len(traj.points[i].positions) != self.
num_joints:
207 res = FollowJointTrajectoryResult()
208 res.error_code=FollowJointTrajectoryResult.INVALID_GOAL
209 msg =
'Command point %d has %d elements for the positions' % (i, len(traj.points[i].positions))
211 self.action_server.set_aborted(result=res, text=msg)
215 if traj.points[i].velocities:
216 seg.velocities[j] = traj.points[i].velocities[lookup[j]]
217 if traj.points[i].positions:
218 seg.positions[j] = traj.points[i].positions[lookup[j]]
220 trajectory.append(seg)
222 rospy.loginfo(
'Trajectory start requested at %.3lf, waiting...', traj.header.stamp.to_sec())
225 while traj.header.stamp > time:
226 time = rospy.Time.now()
229 end_time = traj.header.stamp + rospy.Duration(sum(durations))
230 seg_end_times = [rospy.Time.from_sec(trajectory[seg].start_time + durations[seg])
for seg
in range(len(trajectory))]
232 rospy.loginfo(
'Trajectory start time is %.3lf, end time is %.3lf, total duration is %.3lf', time.to_sec(), end_time.to_sec(), sum(durations))
235 traj_start_time = rospy.Time.now()
237 for seg
in range(len(trajectory)):
238 rospy.logdebug(
'current segment is %d time left %f cur time %f' % (seg, durations[seg] - (time.to_sec() - trajectory[seg].start_time), time.to_sec()))
239 rospy.logdebug(
'goal positions are: %s' % str(trajectory[seg].positions))
242 if durations[seg] == 0:
243 rospy.logdebug(
'skipping segment %d with duration of 0 seconds' % seg)
248 for port, joints
in self.port_to_joints.items():
252 j = self.joint_names.index(joint)
255 if seg != 0: start_position = trajectory[seg - 1].positions[j]
257 desired_position = trajectory[seg].positions[j]
258 desired_velocity = max(self.
min_velocity, abs(desired_position - start_position) / durations[seg])
260 self.msg.desired.positions[j] = desired_position
261 self.msg.desired.velocities[j] = desired_velocity
269 vals.append((master_id, master_pos, spd))
270 vals.append((slave_id, slave_pos, spd))
275 vals.append((motor_id, pos, spd))
277 multi_packet[port] = vals
279 for port, vals
in multi_packet.items():
280 self.
port_to_io[port].set_multi_position_and_speed(vals)
282 while time < seg_end_times[seg]:
285 if self.action_server.is_preempt_requested():
286 msg =
'New trajectory received. Aborting old trajectory.' 289 for port, joints
in self.port_to_joints.items():
298 vals.append((motor_id, pos))
300 multi_packet[port] = vals
302 for port, vals
in multi_packet.items():
303 self.
port_to_io[port].set_multi_position(vals)
305 self.action_server.set_preempted(text=msg)
310 time = rospy.Time.now()
315 res = FollowJointTrajectoryResult()
316 res.error_code=FollowJointTrajectoryResult.PATH_TOLERANCE_VIOLATED
317 msg =
'Unsatisfied position constraint for %s, trajectory point %d, %f is larger than %f' % \
320 self.action_server.set_aborted(result=res, text=msg)
327 rospy.logdebug(
'desired pos was %f, actual pos is %f, error is %f' % (trajectory[-1].positions[i], self.
joint_states[j].current_pos, self.
joint_states[j].current_pos - trajectory[-1].positions[i]))
331 if pos_constraint > 0
and abs(pos_error) > pos_constraint:
332 res = FollowJointTrajectoryResult()
333 res.error_code=FollowJointTrajectoryResult.GOAL_TOLERANCE_VIOLATED
334 msg =
'Aborting because %s joint wound up outside the goal constraints, %f is larger than %f' % \
335 (joint, pos_error, pos_constraint)
337 self.action_server.set_aborted(result=res, text=msg)
340 msg =
'Trajectory execution successfully completed' 342 res = FollowJointTrajectoryResult()
343 res.error_code=FollowJointTrajectoryResult.SUCCESSFUL
344 self.action_server.set_succeeded(result=res, text=msg)
348 while self.
running and not rospy.is_shutdown():
349 self.msg.header.stamp = rospy.Time.now()
354 self.msg.actual.positions[i] = state.current_pos
355 self.msg.actual.velocities[i] = abs(state.velocity)
356 self.msg.error.positions[i] = self.msg.actual.positions[i] - self.msg.desired.positions[i]
357 self.msg.error.velocities[i] = self.msg.actual.velocities[i] - self.msg.desired.velocities[i]
359 self.state_pub.publish(self.
msg)
stopped_velocity_tolerance
def process_command(self, msg)
def process_follow_trajectory(self, goal)
def __init__(self, num_joints)
def process_trajectory(self, traj)
def __init__(self, controller_namespace, controllers)