How to know when each point in the trajectory was executed?
I'm new to ROS. I wrote the code below to execute a trajectory using SimpleActionClient
. I need to know when each point in the trajectory was executed while the trajectory is being executed. I thought to use the feedback callback from action client's send_goal
method, but it's never called. The done_cb
and active_cb
are called, but not feedback_cb
. Then, I thought since each point has time_from_start
field I could listen to /feedback_states
topic (see list of topics below) and check the the time_from_start
field (see the feedback_state
output below). But, it's always 0.
What am I doing wrong? Or, even better, is this how to get what I need or is there another better way?
UPDATE1
Just to clarify, I want to control the Yaskawa hc10 robot from ROS AND be able to know what trajectory point it's currently executing. After the research I saw that I should use motoman driver. I found some python example and continued from there. So, the first part seems to work. But, now I need to make the second part to work. To do that I decided to check the time_from_start
field from the message from /feedback_states
topic since I assign time_from_start
to each point when I build the trajectory object. But, when I do rostopic echo /joint_states
I can see that time_from_start
is always 0 and doesn't have the values I assigned.
Therefore, I decided a different approach - listen to joint_states
topic and do the following:
- I consider 6-joint values as a vector.
- Now, I have the target point (6-joint values) that I want the robot to reach and current positions that I receive from
joint_states
topic. Therefore,
For each received point:
- Calculate distance between current point and target point (
numpy.norm(current_point - target_point)
) - As the arm approaches the target point, the distance (
norm
) value should decrease. If current distance is greater than previous distance, I consider that it has reached the target point.
Does this make sense? I'll post the issues I have with this approach if needed, unless you already know what can be the issues.
Code
client = actionlib.SimpleActionClient('/joint_trajectory_action', FollowJointTrajectoryAction)
if not client.wait_for_server(rospy.Duration(5.0)):
raise RuntimeError("Action server not available!")
def _create_trajpoint(self, joint_positions, time_from_start, velocities) -> JointTrajectoryPoint:
point = JointTrajectoryPoint()
point.positions = joint_positions
point.time_from_start = rospy.Duration(time_from_start)
point.velocities = velocities
return point
def _execute_trajectory(self, traj):
self._send_trajectory_to_controller(traj)
self._wait_for_traj_to_complete()
def _send_trajectory_to_controller(self, traj):
print("Sending trajectory")
goal = FollowJointTrajectoryGoal()
goal.trajectory = traj
self._action_client.send_goal(goal, feedback_cb=my_feedback_cb, done_cb=my_done_cb, active_cb=my_active_cb)
self._action_client.wait_for_result(rospy.Duration(2.0))
print("Trajectory sent")
def _wait_for_traj_to_complete(self):
print('Waiting for trajectory to complete')
wait_time = 0.1
no_motion_total = 0
no_motion_timeout = 1
traj_state = self._action_client.get_state()
while traj_state == actionlib.GoalStatus.ACTIVE:
rospy.sleep(wait_time)
traj_state = self._action_client.get_state()
robot_status = self.get_robot_status()
if robot_status.in_motion.val == 0:
no_motion_total += wait_time
if no_motion_total > no_motion_timeout:
raise RuntimeError(f'Robot hasn\'t moved for {no_motion_timeout} sec. TrajState={traj_state}')
else:
no_motion_total = 0
if traj_state == actionlib ...
Quick note: I don't believe you can. From the messages you show, this looks like
motoman_driver
. Due to how caching works on the MotoROS1 side (it has an internal queue, and the underlying Yaskawa controller code has yet another internal queue), you can't rely on what the driver tells you -- at least not about the state of the action server. What you could do is look at thejoint_states
topic and derive progress from that. That's non-trivial though, as "loops" in a trajectory would make comparisons difficult.I'm sorry there isn't something nicer to write, but I believe it's a fundamental limitation of how the system is implemented (and technically, any driver / robot controller with (an) internal queue(s) would make really knowing how much of a trajectory has been executed impossible, not just in the case of Yaskawa. I only know of Staubli ...(more)
Btw, if you're specifically interested in detecting whether the robot has moved or not, the
robot_status
topic carries that information.What about
/feedback_states
or/joint_trajectory_action/feedback
topics? Why only thepositions
inactual
section is filled but all other is empty? What's the point of these topics then if they don't report data?You'd have to ask the original developers I'm afraid. I can't answer that.
sorry, do you know where would I ask? I thought ROS community is the place to ask.
That would be a post on ros-industrial/motoman/discussions. Note though:
motoman_driver
is really old, almost 12 years now. Only one of the original developers would maybe respond, and I don't know whether he'd still remember.Can I ask what's your recommendation to control the Yaskawa from ROS? Yaskawa have a dedicated driver, but it's not free. If I use ROS, what's my alternative to
motoman_driver
?I'm not sure I understand what you mean by this. Which product are you referring to?
I would not know of an alternative.