Main Content

Generate Code for Motion Planning Using Robot Model Imported from URDF

This example shows how to perform code generation to plan motion using robot model imported from URDF file. For this example, you use a manipulatorRRT object with a imported rigidBodyTree robot model to find a obstacle-free path between two configurations of the robot. After you verify the algorithm in MATLAB®, use the generated MEX file in the algorithm to visualize the robot movement.

Write Algorithm to Plan Path

Create a function, iiwaPathPlanner, that uses a manipulatorRRT object to plan a path between two configurations for the KUKA LBR iiwa 14 robot model in an obstacle filled environment.

function path = iiwaPathPlanner(startConfig, goalConfig, collisionDims, collisionPoses)
    %#codegen

    % Load the rigid body tree for which the planner will be defined 
    % and make it persistent. This improves the run-time performance
    % of the function since the robot need only be instantiated once.
    persistent robot 
    if isempty(robot)
        robot = iiwaForCodegen('row');
    end
    
    collisionObjects = cell(1,length(collisionDims));
    for i=1:length(collisionDims)
        switch length(collisionDims{i})
            case 1
                sphereRadius = collisionDims{i};
                collisionObjects{i} = collisionSphere(sphereRadius{1});
                collisionObjects{i}.Pose = collisionPoses{i};
            case 2
                cylinderDims = collisionDims{i};
                collisionObjects{i} = collisionCylinder(cylinderDims{1}, cylinderDims{2});
                collisionObjects{i}.Pose = collisionPoses{i};
            case 3
                boxDims = collisionDims{i};
                collisionObjects{i} = collisionBox(boxDims{1}, boxDims{2}, boxDims{3});
                collisionObjects{i}.Pose = collisionPoses{i};
        end
    end

    planner = manipulatorRRT(robot, collisionObjects);
    planner.SkippedSelfCollisions = "parent";
    
    path = plan(planner, startConfig, goalConfig);
end

The algorithm acts as a wrapper for a standard RRT motion planning call. It loads the robot inside the function, accepts standard inputs, and returns a set of robot configuration vectors as the path. Since you cannot use handle objects as the input or output for functions that are supported for code generation. Save the iiwaPathPlanner function in your current folder.

Verify Motion Planning Algorithm in MATLAB

Verify the motion planning algorithm in MATLAB before generating code.

Import a KUKA LBR iiwa 14 robot model and the Robotiq 2F85 gripper model as rigidBodyTree objects. Set the data format to "row".

robot = importrobot('iiwa14.urdf',DataFormat="row");
gripper = loadrobot('robotiq2F85',DataFormat="row");

Incorporate the rigidBodyTree object for the gripper into the rigidBodyTree object for the robot.

addSubtree(robot,"iiwa_link_ee_kuka",gripper,ReplaceBase=true)

Each finger of the Robotiq gripper contains a five-bar linkage. Since closed chains are not supported in rigidBodyTree objects, part of the gripper is always in self-collision. The exampleHelperClearCollisions function prevents the self-collision by clearing the collision mesh of one of the two colliding bodies in each finger.

robot = exampleHelperClearCollisions(robot);

Use the writeAsFunction function to load the rigidBodyTree of the modified robot for code generation.

writeAsFunction(robot,'iiwaForCodegen');

As of MATLAB R2021b, an unmodified rigidBodyTree object can be called directly with importrobot in codegen. It is also possible to directly modify the robot in the function used for code generation.

Create a simple environment with obstacles using collision primitives.

env = {collisionBox(0.5, 0.5, 0.05),collisionSphere(0.15)};
env{1}.Pose = trvec2tform([0.35 0.35 0.3]);
env{2}.Pose = trvec2tform([-0.25 0.1 0.6]);

Define a start and goal configuration. You must specify a start and goal that do not overlap with the obstacles. Otherwise, the planner throws an error.

startConfig = robot.homeConfiguration;
goalConfig = [-2.9236 1.8125 0.6484 1.6414 -0.4698 -0.4181 0.3295 0 0 0 0 0 0];

Visualize initial and final positions of the robot.

figure; 
show(robot,startConfig); 
hold all; 
show(robot,goalConfig);
show(env{1});
show(env{2});

Extract the collision data from the environment.

collisionDims = {{env{1}.X env{1}.Y env{1}.Z},{env{2}.Radius}};
collisionPoses = cellfun(@(x)(x.Pose),env,'UniformOutput',false);

Plan the path.

path = iiwaPathPlanner(startConfig,goalConfig,collisionDims,collisionPoses);

Visualize the robot. Set the 'FastUpdate' option of the show method to true to get a smooth animation.

figure;
ax = show(robot,startConfig);
hold all
show(env{1},'Parent',ax);
show(env{2},'Parent',ax);
rrt = manipulatorRRT(robot,env);
interpPath = interpolate(rrt,path);
for i = 1:size(interpPath,1)
    show(robot,interpPath(i,:),'PreservePlot',false,'FastUpdate',true);
    drawnow;
end

Generate Code for Motion Planning Algorithm

You can use either the codegen (MATLAB Coder) function or the MATLAB Coder (MATLAB Coder) app to generate code. For this example, generate a MEX file by calling codegen at the MATLAB command line. Specify sample input arguments for each input to the function using the -args input argument.

Call the codegen function and specify the input arguments in a cell array. This function creates a separate iiwaPathPlanner_mex function to use. You can also produce C code by using the options input argument. This step can take some time.

codegen iiwaPathPlanner -args {startConfig,goalConfig,collisionDims,collisionPoses}
Code generation successful.

Verify Results Using Generated MEX Function

Plan the path by calling the MEX version of the motion planning algorithm for the specified start and goal configurations, and collision data from the environment.

path = iiwaPathPlanner_mex(startConfig,goalConfig,collisionDims,collisionPoses);

Visualize the robot with the robot configurations computed using the MEX version of the motion planning algorithm. Set the 'FastUpdate' option of the show method to true to get a smooth animation.

figure;
ax = show(robot,startConfig);
hold all
show(env{1},'Parent',ax);
show(env{2},'Parent',ax);

interpPath = interpolate(rrt,path);
for i = 1:size(interpPath,1)
    show(robot,interpPath(i,:),'PreservePlot',false,'FastUpdate',true);
    drawnow;
end