37 from __future__
import division
38 from threading
import Thread
43 from std_msgs.msg
import Float64
44 from svenzva_msgs.msg
import MotorState, MotorStateList
45 from trajectory_msgs.msg
import JointTrajectory
46 from control_msgs.msg
import FollowJointTrajectoryAction
47 from control_msgs.msg
import FollowJointTrajectoryFeedback
48 from control_msgs.msg
import FollowJointTrajectoryResult
59 def __init__(self, controller_namespace, mx_io, states):
69 self.
joint_names = rospy.get_param(
'joint_names', [
'joint_1',
'joint_2',
'joint_3',
'joint_4',
'joint_5',
'joint_6'])
74 self.joint_names.remove(
'finger_joint_1')
76 self.joint_names.remove(
'finger_joint_2')
78 rospy.Subscriber(
"revel/motor_states", MotorStateList, self.
motor_state_cb, queue_size=1)
95 self.goal_constraints.append(rospy.get_param(ns +
'/' + joint +
'/goal', -1.0))
96 self.trajectory_constraints.append(rospy.get_param(ns +
'/' + joint +
'/trajectory', -1.0))
99 self.
msg = FollowJointTrajectoryFeedback()
101 self.msg.desired.positions = [0.0] * self.
num_joints 102 self.msg.desired.velocities = [0.0] * self.
num_joints 103 self.msg.desired.accelerations = [0.0] * self.
num_joints 104 self.msg.actual.positions = [0.0] * self.
num_joints 105 self.msg.actual.velocities = [0.0] * self.
num_joints 106 self.msg.error.positions = [0.0] * self.
num_joints 107 self.msg.error.velocities = [0.0] * self.
num_joints 120 FollowJointTrajectoryAction,
123 self.action_server.start()
130 if self.action_server.is_active(): self.action_server.set_preempted()
132 while self.action_server.is_active():
141 num_points = len(traj.points)
145 cur_pos.append( ( i+1, SvenzvaDriver.rad_to_raw(self.
motor_states[i].position )))
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={}' % (set(self.
joint_names)))
154 rospy.logerr(
' traj.joint_names={}' % (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())
224 while traj.header.stamp > time:
225 time = rospy.Time.now()
228 end_time = traj.header.stamp + rospy.Duration(sum(durations))
229 seg_end_times = [rospy.Time.from_sec(trajectory[seg].start_time + durations[seg])
for seg
in range(len(trajectory))]
231 rospy.loginfo(
'Trajectory start time is %.3lf, end time is %.3lf, total duration is %.3lf', time.to_sec(), end_time.to_sec(), sum(durations))
234 traj_start_time = rospy.Time.now()
236 for seg
in range(len(trajectory)):
237 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()))
238 rospy.logdebug(
'goal positions are: %s' % str(trajectory[seg].positions))
241 if durations[seg] == 0:
242 rospy.logdebug(
'skipping segment %d with duration of 0 seconds' % seg)
247 j = self.joint_names.index(joint)
250 if seg != 0: start_position = trajectory[seg - 1].positions[j]
252 desired_position = trajectory[seg].positions[j]
253 desired_velocity = max(self.
min_velocity, abs(desired_position - start_position) / durations[seg])
255 self.msg.desired.positions[j] = desired_position
256 self.msg.desired.velocities[j] = desired_velocity
260 pos = SvenzvaDriver.rad_to_raw(desired_position * self.
gear_ratios[j])
261 spd = SvenzvaDriver.spd_rad_to_raw(desired_velocity * self.
gear_ratios[j])
262 vals.append((motor_id, pos, spd))
263 self.mx_io.set_multi_position_and_speed(vals)
265 while time < seg_end_times[seg]:
268 if self.action_server.is_preempt_requested():
269 msg =
'New trajectory received. Aborting old trajectory.' 276 pos = SvenzvaDriver.rad_to_raw(cur_pos)
278 vals.append((motor_id, pos, 0))
280 self.mx_io.set_multi_position_and_speed(vals)
281 self.action_server.set_preempted(text=msg)
286 time = rospy.Time.now()
291 res = FollowJointTrajectoryResult()
292 res.error_code=FollowJointTrajectoryResult.PATH_TOLERANCE_VIOLATED
293 msg =
'Unsatisfied position constraint for %s, trajectory point %d, %f is larger than %f' % \
296 self.action_server.set_aborted(result=res, text=msg)
303 rospy.logdebug(
'desired pos was %f, actual pos is %f, error is %f' % (trajectory[-1].positions[i], self.
motor_states[i].position, self.
motor_states[i].position - trajectory[-1].positions[i]))
307 if pos_constraint > 0
and abs(pos_error) > pos_constraint:
308 res = FollowJointTrajectoryResult()
309 res.error_code=FollowJointTrajectoryResult.GOAL_TOLERANCE_VIOLATED
310 msg =
'Aborting because %s joint wound up outside the goal constraints, %f is larger than %f' % \
311 (joint, pos_error, pos_constraint)
313 self.action_server.set_aborted(result=res, text=msg)
316 msg =
'Trajectory execution successfully completed' 318 res = FollowJointTrajectoryResult()
319 res.error_code=FollowJointTrajectoryResult.SUCCESSFUL
320 self.action_server.set_succeeded(result=res, text=msg)
324 while self.
running and not rospy.is_shutdown():
325 self.msg.header.stamp = rospy.Time.now()
330 self.msg.actual.positions[i] = state.position
331 self.msg.actual.velocities[i] = abs(state.speed)
332 self.msg.error.positions[i] = self.msg.actual.positions[i] - self.msg.desired.positions[i]
333 self.msg.error.velocities[i] = self.msg.actual.velocities[i] - self.msg.desired.velocities[i]
335 self.state_pub.publish(self.
msg)
def __init__(self, num_joints)
def process_follow_trajectory(self, goal)
def motor_state_cb(self, data)
def process_command(self, msg)
stopped_velocity_tolerance
def __init__(self, controller_namespace, mx_io, states)
def process_trajectory(self, traj)