MATLAB Coder "Cannot allocate this handle object"
6 views (last 30 days)
Show older comments
I'm currently trying to generate a mex file/c++ code that I can later call from my Simulink model. The purpose of this code is to solve the inverse kinematics (IK) of a robot in my lab, with constraints, so unfortunatly I cannot use the standard IK block from the Robotics System Toolbox.
In order to reduce the computational cost of this code I have declared some objects as persistant. These include the rigidbodytree, the generalized inverse kinematics (GIK) solver and the constraints for the GIK solver. My code can be seen below.
function [q] = micoGIK(q0,transformTarget)
%MicoGIK This function solves the IK for the Mico given constraints defined above
% This funciton is ultimatly compiled as C code so that is can be called from Simulink
%Define persistent variables which will only need to be initialized once
persistent mico
persistent gik
persistent remainAboveTable
persistent jointLimits
%The code immediatly below is only run once. Variables remain defined between time steps to avoid excessive computational resources.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
if isempty(mico)
%Create Mico Object
mico=micoCodeGen;
%Create the generalized IK solver object
gik=generalizedInverseKinematics('RigidBodyTree',mico,'ConstraintInputs',{'pose','cartesian','joint'});
%Create a constraint so that the EE never dips below the table
remainAboveTable=constraintCartesianBounds('EE');
remainAboveTable.Bounds=[-inf,inf;-inf,inf;-inf,0.05];
%Create joint constraints
jointLimits=constraintJointBounds(mico);
jointLimits.Bounds=[-pi ,pi;
pi/2 ,3*pi/2;
pi/4 ,7*pi/8;
-2*pi ,2*pi;
-2*pi ,2*pi;
-2*pi ,2*pi];
jointLimits.Weights=[1 1 0.8 0.8 0.8 0.8];
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%Create constraint for pose. This is redefined at each time step
poseConstraint=constraintPoseTarget('EE','TargetTransform',transformTarget);
%Call the gik
[q,~]=gik(q0,poseConstraint,remainAboveTable,jointLimits);
end
I get an error on the last line of code:
[q,~]=gik(q0,poseConstraint,remainAboveTable,jointLimits);
The error message reads:
"Cannot allocate this handle object. For code generation, if a persistent variable references a handle object, you can create the handle object only once per program."
I've refered to the documentation: Handle Object Limitations for Code Generation and cannot determine what limitation rules I have broken. I've embedded the initalization of all the persistant object within the isempty() safeguard.
The error message confuses me as the only variable being intialized, at the line that causes the error, is non-persistent. I should note that if I comment out the line causing the errors and hard code an output in place of that line then MATLAB coder can generate the code with no issues. This result makes me inclined to believe that I have declared and initialized my persistant variables properly for code generation.
0 Comments
Answers (2)
Mukund Sankaran
on 15 Sep 2021
Hi Chris,
In the code you've shared, if you don't make the variable named "gik" persistent, does code generation succeed ? If it does, then here is my guess as to what might be happening.
The following line in your code creates a handle object (not a singleton) named "poseConstraint".
poseConstraint = constraintPoseTarget('EE','TargetTransform',transformTarget);
When this handle object is then passed as an argument in the call to the persistent System object named "gik", the internals of that call may be making the persistent variable refer to the handle object, which is not a singleton here, and would therefore violate the constraint "A Handle Object That a Persistent Variable Refers To Must Be a Singleton Object" in the link to the documentation you shared.
Here is a simple example showing the same problem as the one you are observing:
myFunc.m
%#codegen
function out = myFunc(in1, in2)
persistent mySystemObj;
if isempty(mySystemObj)
mySystemObj = MySystemObject;
end
myHandleClass = MyHandleClass(in1);
out = mySystemObj(myHandleClass, in2);
end
MySystemObject.m
classdef MySystemObject < matlab.System
properties (Hidden, Access = private)
prop
end
methods (Access = protected)
function y = stepImpl(obj, handleObj, inc)
obj.prop = handleObj;
y = handleObj.prop + inc;
end
end
end
MyHandleClass.m
classdef MyHandleClass < handle
properties
prop
end
methods
function obj = MyHandleClass(inputArg1)
obj.prop = inputArg1;
end
end
end
Now try to generate code for myFunc and you will see this
As the following line in the stepImpl method of MySystemObject.m makes it reference the handle object (which is not a singleton) that is passed in, you either have to make the myHandleClass variable in myFunc.m persistent too or not make the mySystemObj variable persistent in order for code generation to succeed.
obj.prop = handleObj;
Hope this helps
Karsh Tharyani
on 16 Sep 2021
Hi Chris,
I am sorry that you are seeing this issue. We have gotten reports of the same and a fix has been made in R2021b. If you have a license that allows you access to the pre-release, you can try and see if the issue is resolved.
If you still see the issue on your end, please do not hesitate to reach out to Technical Support https://www.mathworks.com/support/contact_us.html
Best,
Karsh
See Also
Categories
Find more on Code Generation in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!