Coordinated Motion with a Linear Axis
Brief: we demonstrate how to perform coordinated motion in the wrold frame with a robot mounted on a linear axis.
URScript API functions used in this example:
The example program adds and configures a linear axis, attaches the robot base to the axis, and then performs a motion where the robot’s TCP follows a stationary trajectory in the world frame while the linear axis (and attached robot base) are in motion.
Here is the example in greater detail:
Configuring the Axis
The robot first executes a subprogram called ConfigLinearAxis:
that adds a new axis group called “positioner” and a linear axis called “axis1”:
global PI = acos(-1)
POSITIONER_AXIS_TYPE = 1 # 0:revolute, 1:prismatic
POSITIONER_VELOCITY_LIMIT = 0.7*2 # m/s
POSITIONER_ACCELERATION_LIMIT = 0.1*100 # m/s^2
POSITIONER_ENCODER_RESOLUTION = 3600
POSITIONER_FEED_CONSTANT = 1
POSITIONER_GEAR_RATIO = 10
POSITIONER_ZERO_OFFSET = 0
AXIS_CALIBRATION = p[0,0,0,d2r(90),0,0] # calibration in the "positioner" frame
# stop EtherCAT master first, otherwise, reset_world_model will throw an error
ethercat_stop(True)
reset_world_model()
axis_group_add("positioner", p[0,0,0,0,0,0], "base")
axis_group_add_axis("positioner", "axis1", "", AXIS_CALIBRATION, POSITIONER_AXIS_TYPE, POSITIONER_VELOCITY_LIMIT, POSITIONER_ACCELERATION_LIMIT)
ethercat_config_axis("axis1", 1, POSITIONER_ENCODER_RESOLUTION, POSITIONER_GEAR_RATIO, POSITIONER_FEED_CONSTANT, POSITIONER_ZERO_OFFSET)
ethercat_start(10)
ethercat_enable_axis("axis1")
The gear ratio, feed constant, encoder resolution parameters, limits, etc., are for a hypothetical positioner. In the simulation, the axis starts with an encoder position of 0, which places its frame position coincident with the “world” frame.
Adding Waypoints
The robot then executes a subprogram called SetUpWaypoints:
This data for three waypoints that all defined in the “world” frame. The data is stored in two formats to be used later in the program. The variables WP1_in_world, WP2_in_world, and WP3_in_world are URScript poses represented in the “world” coordinate system. Additionally, three frames are added “WP1”, “WP2” and “WP3” using the WP1_in_world, WP2_in_world, and WP3_in_world poses. By default, new frames are attached to the “world” frame so they will remain stationary when the external axis moves the robot base. Only one of these forms of waypoint representation is needed for a program to work, but we are using both just to show examples of usage later.
Setting TCP, Robot Base Attachment, and Initial Configuration
Next, the robot sets its TCP, attaches its “base” frame to the external axis, and moves to the initial configuration:
The call attach_frame(“base”, “axis1”) informs the system that the robot’s base is rigidly attached to “axis1” and moves with it at all times. This is a critical call that sets up the configuration of the system. Without it, the robot won’t know that its base moves with the axis.
The call movel(“WP1”) commands the TCP to move to the pose of “WP1”. This uses the world model functionality described here.
Coordinated Motion in the World Frame
Next, coordinated motion is begun by enabling frame tracking on the “world” frame:
In general, frame tracking commands the robot to make the TCP motion relative to the tracked frame even when the tracked frame is moving. If you enable frame tracking on the “world” frame, the TCP motion is relative to the “world” frame, which is fixed.
The robot then performs a series of movep_with_axis_group commands demonstrating two different ways to specify waypoints. The first way specifies a waypoint using the name of a frame (see the first two move commands in the example below). The second is to use a struct that stores a pose and the name of a frame that the pose is defined relative to (see the last two move commands in the example below). The two methods are equivalent, but specified differently. For programs that have many waypoints, the struct form of input may be preferrable to the frame name method because there is a limit of 50 frames in the controller’s memory.
Finally, the last call disables frame tracking: