Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5

Move between two targets and maintain tool orientation

#1
Hi, I'm programming a UR10 to repeatedly move back and forth between targets A and B with a hexagon-shaped "tool" that has a picture on each of it's 6 sides. At target B there is a camera which will look at the picture. Every N cycles I want to rotate the tool to a different picture while it is at target A (out of the camera's view). After rotating the tool the robot repeats the cycle with the new picture.

The problem I am having is the tool always rotates to the desired image WHILE it moves to target B and rotates back to the first image WHILE it returns to target A.

Instead, I need it to:
  1. Start at target A
  2. Rotate tool to the desired image
  3. 移动到目标B同时保持方向
  4. Return to target A while maintaining orientation
  5. 代表eat steps 3 and 4 N times
  6. Rotate tool to the next desired image (while at target A)
  7. 代表eat steps 3-6 until all images have been shown.
I have a simple program called "show_from_right" defined within the RoboDK GUI which executes the moves between A and B. I'm using Python to call this program and run the code that changes which image is shown in between program calls. The images below (next post) show the setup. Here is my code for changing which picture is shown (it runs in a wrapper around the API)

Code:
def set_picture(self, new_pic_idx):
""" Rotate the tool so that the given new_pic_idx is the picture that will be shown to the camera """
new_pic_angle = (new_pic_idx - 1) * -self.deg_per_idx # Calculate the new picture angle
new_pose= robomath.rotz(new_pic_angle * self.d2r) # Calculate the new pose (d2r converts deg to radians)
result = self.robot.setPoseTool(new_pose) # Move the robot to the new pose
self.current_pic_idx = new_pic_idx # Update the current picture index
self.robot.WaitMove(timeout=5000)

Hopefully someone can help me understand what I am doing wrong here!

#2
setPoseTool is not a command that will provoke a robot movement. This function only updates the Tool (TCP) in RoboDK and the real robot if you are connected with the driver.

You should move the robot using a MoveJ or a MoveL command. Example:
Code:
...
robot.setPoseTool(new_tool) # Update the TCP
...
robot.MoveJ(new_pose) # Move the robot. Blocking by default
#3
Thanks for the reply! I've updated my code and here's where I am at now:

The tool instantly rotates to the selected image when I call set_picture(pic_idx) from python (jupyter), great!


Any time I use set_picture to rotate the tool 180deg in one move (moving from picture 1 -> 4 for example) the robot goes crazy and tries to twist itself into a pretzel. I can make incremental moves (1 -> 3 -> 5) that when summed exceed 180 just fine; or if I go 1 -> 6 it turns the opposite direction with no issues. I even tried adding some logic to add or subtract 1deg if the new angles is abs(180) resulting in -179deg or 179deg and this still causes the robot to go crazy. What am I doing wrong here?


Here is the updated code:
Code:
self.deg_per_idx = 360/6 # Divide 360deg by the 6 sides of the hexagon
self.d2r = 0.017453292519943295 # Myltiply by this value to convert degrees to radians

def set_picture(self, new_pic_idx):
""" Rotate the tool so that the given new_pic_idx is the picture that will be shown to the camera """
# The next line calculates how many degrees to rotate from the current pic_idx to the new_pic_idx
new_pic_angle = ((self.current_pic_idx - 1) * -self.deg_per_idx) - ((new_pic_idx - 1) * -self.deg_per_idx)
curr_pose = self.robot.Pose() # Get the robot's current pose
new_pose= robomath.rotz(new_pic_angle * self.d2r) # Calculate the new pose (d2r converts deg to radians)
result = self.robot.MoveJ(curr_pose * new_pose) # Move the robot to the new pose
self.current_pic_idx = new_pic_idx # Update the current picture index
self.robot.WaitMove(timeout=5000)
#4
I decided to break the single 180deg rotation into two 90deg rotations which does work without the robot going off the rails. It's not ideal because it pauses half way through the rotation but that won't interfere with my testing so I'll just use it this way.
#5
Here is my new code. It gives me the results I want! But it seems overly complicated.

I'm rotating the tool then modifying the TCP so that it aligns with the picture I want to show and the camera target.

I'm open to suggestions for a more elegant way to do this - or let me know if this is actually the right way.

Code:
def set_picture(self, new_pic_idx):
""" Rotate the end effector so that the given new_pic_idx is the picture that will be shown to the camera """
if 0 < new_pic_idx <= self.num_pic_idx and isinstance(new_pic_idx, int): # If the new picture index is valid
new_pic_angle = ((self.current_pic_idx - 1) * -self.deg_per_idx) - ((new_pic_idx - 1) * -self.deg_per_idx)
new_tcp_angle = (new_pic_idx - 1) * -self.deg_per_idx # I don't know why I have to calculate this differently but it works

# If the angle is 180 it confuses the robot so we divide the move into 2x -90deg moves (+90 causes problems)
if abs(new_pic_angle) == 180:
for _ in range(2):
half_angle = -90
curr_pose = self.robot.Pose() # Get the robot's current pose
new_pose= robomath.rotz(half_angle * self.d2r) # Generate the rotation matrix
self.robot.MoveJ(curr_pose * new_pose) # Move the robot to the new pose
else:
curr_pose = self.robot.Pose() # Get the robot's current pose
new_pose= robomath.rotz(new_pic_angle * self.d2r) # Generate the rotation matrix
self.robot.MoveJ(curr_pose * new_pose) # Move the robot to the new pose

tcp_pose = robomath.rotz(new_tcp_angle * self.d2r) # Generate a rotation matrix for the TCP
self.robot.setPoseTool(tcp_pose) # Set the new TCP
self.robot.WaitMove(timeout=5000)
self.current_pic_idx = new_pic_idx # Update the current picture index




Users browsing this thread:
1 Guest(s)