This example shows how to use generalized inverse kinematics to plan a joint-space trajectory for a robotic manipulator. It combines multiple constraints to generate a trajectory that guides the gripper to a cup resting on a table. These constraints ensure that the gripper approaches the cup in a straight line and that the gripper remains at a safe distance from the table, without requiring the poses of the gripper to be determined in advance.
Set Up the Robot Model
This example uses a model of the KUKA LBR iiwa, a 7 degree-of-freedom robot manipulator.
importrobot
generates a
rigidBodyTree
model from a description stored in a Unified Robot Description Format (URDF) file.
Define dimensions for the cup.
Create a frame representing the center of the cup positioned relative to the robot base frame.
Define the Planning Problem
The goal of this example is to generate a sequence of robot configurations that satisfy the following criteria:
Start in the home configuration
No abrupt changes in robot configuration
Keep the gripper at least 5 cm above the "table" (z = 0)
The gripper should be aligned with the cup as it approaches
Finish with the gripper 5 cm from the center of the cup
This example utilizes constraint objects to generate robot configurations that satisfy these criteria. The generated trajectory consists of five configuration waypoints. The first waypoint, q0
, is set as the home configuration. Pre-allocate the rest of the configurations in qWaypoints
using repmat
.
Create a
generalizedInverseKinematics
solver that accepts the following constraint inputs:
Cartesian bounds - Limits the height of the gripper.
A position target - Specifies the position of the cup relative to the gripper.
An aiming constraint - Aligns the gripper with the cup axis.
An orientation target - Maintains a fixed orientation for the gripper while approaching the cup.
Joint position bounds - Limits the change in joint positions between waypoints.
gik =
generalizedInverseKinematics with properties:
NumConstraints: 5
ConstraintInputs: {'cartesian' 'position' 'aiming' 'orientation' 'joint'}
RigidBodyTree: [1×1 rigidBodyTree]
SolverAlgorithm: 'BFGSGradientProjection'
SolverParameters: [1×1 struct]
Create Constraint Objects
Create the constraint objects that are passed as inputs to the solver. These object contain the parameters needed for each constraint. Modify these parameters between calls to the solver as necessary.
Create a Cartesian bounds constraint that requires the gripper to be at least 5 cm above the table (negative z direction). All other values are given as inf
or -inf
.
heightAboveTable =
constraintCartesianBounds with properties:
EndEffector: 'iiwa_link_ee_kuka'
ReferenceBody: ''
TargetTransform: [4×4 double]
Bounds: [3×2 double]
Weights: [1 1 1]
Create a constraint on the position of the cup relative to the gripper, with a tolerance of 5 mm.
distanceFromCup =
constraintPositionTarget with properties:
EndEffector: 'cupFrame'
ReferenceBody: 'iiwa_link_ee_kuka'
TargetPosition: [0 0 0]
PositionTolerance: 0.0050
Weights: 1
Create an aiming constraint that requires the z-axis of the iiwa_link_ee
frame to be approximately vertical, by placing the target far above the robot. The iiwa_link_ee
frame is oriented such that this constraint aligns the gripper with the axis of the cup.
alignWithCup =
constraintAiming with properties:
EndEffector: 'iiwa_link_ee'
ReferenceBody: ''
TargetPoint: [0 0 100]
AngularTolerance: 0
Weights: 1
Create a joint position bounds constraint. Set the Bounds
property of this constraint based on the previous configuration to limit the change in joint positions.
limitJointChange =
constraintJointBounds with properties:
Bounds: [7×2 double]
Weights: [1 1 1 1 1 1 1]
Create an orientation constraint for the gripper with a tolerance of one degree. This constraint requires the orientation of the gripper to match the value specified by the TargetOrientation
property. Use this constraint to fix the orientation of the gripper during the final approach to the cup.
fixOrientation =
constraintOrientationTarget with properties:
EndEffector: 'iiwa_link_ee_kuka'
ReferenceBody: ''
TargetOrientation: [1 0 0 0]
OrientationTolerance: 0.0175
Weights: 1
Find a Configuration That Points at the Cup
This configuration should place the gripper at a distance from the cup, so that the final approach can be made with the gripper properly aligned.
Constraint objects have a Weights
property which determines how the solver treats conflicting constraints. Setting the weights of a constraint to zero disables the constraint. For this configuration, disable the joint position bounds and orientation constraint.
Set the target position for the cup in the gripper frame. The cup should lie on the z-axis of the gripper at the specified distance.
Solve for the robot configuration that satisfies the input constraints using the gik
solver. You must specify all the input constraints. Set that configuration as the second waypoint.
Find Configurations That Move Gripper to the Cup Along a Straight Line
Re-enable the joint position bound and orientation constraints.
Disable the align-with-cup constraint, as the orientation constraint makes it redundant.
Set the orientation constraint to hold the orientation based on the previous configuration (qWaypoints(2,:)
). Get the transformation from the gripper to the base of the robot model. Convert the homogeneous transformation to a quaternion.
Define the distance between the cup and gripper for each waypoint.
Define the maximum allowed change in joint positions between each waypoint.
Call the solver for each remaining waypoint.
Visualize the Generated Trajectory
Interpolate between the waypoints to generate a smooth trajectory. Use
pchip
to avoid overshoots, which might violate the joint limits of the robot.
Compute the gripper position for each interpolated configuration.
Show the robot in its initial configuration along with the table and cup.
Animate the manipulator and plot the gripper position.
If you want to save the generated configurations to a MAT-file for later use, execute the following:
>> save('lbr_trajectory.mat', 'tWaypoints', 'qWaypoints');