我正在Simulink中编写2级Matlab S-Function。在尝试构建时,我收到以下错误:
Reference to non-existent field 'SetPreCompInpPortInfoToDynamic'
我的设置功能的第一位是:
function setup(block)
% Register number of ports
block.NumInputPorts = 4;
block.NumOutputPorts = 3;
% Setup port properties to be inherited or dynamic
block.SetPreCompInpPortInfoToDynamic;
block.SetPreCompOutPortInfoToDynamic;
% Override input port properties
for i=1:block.NumInputPorts
block.InputPort(i).Dimensions = 1;
block.InputPort(i).DatatypeID = 0; % double
block.InputPort(i).Complexity = 'Real';
block.InputPort(i).DirectFeedthrough = false;
end
构建工作正常,将值赋值给block
(传递给我的S函数的对象)。它只会在引用block
的回调时窒息。
这让我认为block
作为一种不同类型的对象而不是RunTimeBlock
对象传递给我的S-Function,但我不确定。
我尝试直接将Simulink.RunTimeBlock
导入到该函数中,但它没有任何区别。
以前在几个地方(这里是一个)问过这个问题: http://mathforum.org/kb/message.jspa?messageID=7049610
但是,我无法找到答案的任何地方。
非常感谢任何帮助。
根据评论的要求: 我的模型图片(这很简单,因为我只是先测试S函数):
完整的S-Function代码(注意它很长,但更新函数只包含大量的数学运算):
function Canfield_S_Function(block)
import Simulink.RunTimeBlock;
%MSFUNTMPL_BASIC A Template for a Level-2 MATLAB S-Function
% The MATLAB S-function is written as a MATLAB function with the
% same name as the S-function. Replace 'msfuntmpl_basic' with the
% name of your S-function.
%
% It should be noted that the MATLAB S-function is very similar
% to Level-2 C-Mex S-functions. You should be able to get more
% information for each of the block methods by referring to the
% documentation for C-Mex S-functions.
%
% Copyright 2003-2010 The MathWorks, Inc.
%%
%% The setup method is used to set up the basic attributes of the
%% S-function such as ports, parameters, etc. Do not add any other
%% calls to the main body of the function.
%%
setup(block);
%endfunction
%% Function: setup ===================================================
%% Abstract:
%% Set up the basic characteristics of the S-function block such as:
%% - Input ports
%% - Output ports
%% - Dialog parameters
%% - Options
%%
%% Required : Yes
%% C-Mex counterpart: mdlInitializeSizes
%%
function setup(block)
% Register number of ports
block.NumInputPorts = 4;
block.NumOutputPorts = 3;
% Setup port properties to be inherited or dynamic
block.SetPreCompInpPortInfoToDynamic;
block.SetPreCompOutPortInfoToDynamic;
% Override input port properties
for i=1:block.NumInputPorts
block.InputPort(i).Dimensions = 1;
block.InputPort(i).DatatypeID = 0; % double
block.InputPort(i).Complexity = 'Real';
block.InputPort(i).DirectFeedthrough = false;
end
% Override output port properties
for j=1:block.NumOutputPorts
block.OutputPort(j).Dimensions = 1;
block.OutputPort(j).DatatypeID = 0; % double
block.OutputPort(j).Complexity = 'Real';
end
% Register parameters
block.NumDialogPrms = 4;
% Register sample times
% [0 offset] : Continuous sample time
% [positive_num offset] : Discrete sample time
%
% [-1, 0] : Inherited sample time
% [-2, 0] : Variable sample time
block.SampleTimes = [-1 0];
% Specify the block simStateCompliance. The allowed values are:
% 'UnknownSimState', < The default setting; warn and assume DefaultSimState
% 'DefaultSimState', < Same sim state as a built-in block
% 'HasNoSimState', < No sim state
% 'CustomSimState', < Has GetSimState and SetSimState methods
% 'DisallowSimState' < Error out when saving or restoring the model sim state
block.SimStateCompliance = 'DefaultSimState';
%% -----------------------------------------------------------------
%% The MATLAB S-function uses an internal registry for all
%% block methods. You should register all relevant methods
%% (optional and required) as illustrated below. You may choose
%% any suitable name for the methods and implement these methods
%% as local functions within the same file. See comments
%% provided for each function for more information.
%% -----------------------------------------------------------------
block.RegBlockMethod('PostPropagationSetup', @DoPostPropSetup);
block.RegBlockMethod('InitializeConditions', @InitializeConditions);
%block.RegBlockMethod('Start', @Start);
block.RegBlockMethod('Outputs', @Outputs); % Required
block.RegBlockMethod('Update', @Update);
%block.RegBlockMethod('Derivatives', @Derivatives);
%block.RegBlockMethod('Terminate', @Terminate); % Required
end setup
%%
%% PostPropagationSetup:
%% Functionality : Setup work areas and state variables. Can
%% also register run-time methods here
%% Required : No
%% C-Mex counterpart: mdlSetWorkWidths
%%
function DoPostPropSetup(block)
block.NumDworks = 4;
block.Dwork(1).Name = 'x1';
block.Dwork(1).Dimensions = 1;
block.Dwork(1).DatatypeID = 0; % double
block.Dwork(1).Complexity = 'Real'; % real
block.Dwork(1).UsedAsDiscState = true;
block.Dwork(2).Name = 'x2';
block.Dwork(2).Dimensions = 1;
block.Dwork(2).DatatypeID = 0; % double
block.Dwork(2).Complexity = 'Real'; % real
block.Dwork(2).UsedAsDiscState = true;
block.Dwork(3).Name = 'x3';
block.Dwork(3).Dimensions = 1;
block.Dwork(3).DatatypeID = 0; % double
block.Dwork(3).Complexity = 'Real'; % real
block.Dwork(3).UsedAsDiscState = true;
block.Dwork(4).Name = 'x4';
block.Dwork(4).Dimensions = 1;
block.Dwork(4).DatatypeID = 0; % double
block.Dwork(4).Complexity = 'Real'; % real
block.Dwork(4).UsedAsDiscState = true;
end DoPostPropSetup
%%
%% InitializeConditions:
%% Functionality : Called at the start of simulation and if it is
%% present in an enabled subsystem configured to reset
%% states, it will be called when the enabled subsystem
%% restarts execution to reset the states.
%% Required : No
%% C-MEX counterpart: mdlInitializeConditions
%%
function InitializeConditions(block)
block.Dwork(1).Data = block.DialogPrm(1).Data;
block.Dwork(2).Data = block.DialogPrm(2).Data;
block.Dwork(3).Data = block.DialogPrm(3).Data;
block.Dwork(4).Data = block.DialogPrm(4).Data;
end InitializeConditions
%%
%% Outputs:
%% Functionality : Called to generate block outputs in
%% simulation step
%% Required : Yes
%% C-MEX counterpart: mdlOutputs
%%
function Outputs(block)
block.OutputPort(1).Data = block.Dwork(1).Data;
block.OutputPort(2).Data = block.Dwork(2).Data;
block.OutputPort(3).Data = block.Dwork(3).Data;
end Outputs
%%
%% Update:
%% Functionality : Called to update discrete states
%% during simulation step
%% Required : No
%% C-MEX counterpart: mdlUpdate
%%
function Update(block)
%specify a pointing vector and plunge distance, convert vector to unit
%vector
tVec = [block.InputPort(1).Data,block.InputPort(2).Data,block.InputPort(3).Data]; %pointing vector
tVec = tVec/norm(tVec);
plunge = block.InputPort(4).Data; %plunge dist
%find the bending vector and angle
u_Bend = cross(tVec, [0,0,1])/norm(cross(tVec, [0,0,1]));
phi = acos(dot(tVec, [0,0,1]));
%Find coordinates of distal revolutes about wrist center when joint is at rest
rev_Dist = 3.17200333; %Distance from plate center
arm_L = 5.1; %arm length
d1p = [0;rev_Dist; plunge];
d2p = [rev_Dist*cos(30);-1*rev_Dist*sin(30);plunge];
d3p = [-1*rev_Dist*cos(30);-1*rev_Dist*sin(30);plunge];
nu = 1-cos(phi);
c = cos(phi);
s = sin(phi);
%Transformation matrix: convert at-rest distal revolutes to pointed distal
%revolutes
R = [u_Bend(1)*u_Bend(1)*nu+c, u_Bend(1)*u_Bend(2)*nu-u_Bend(3)*s, u_Bend(2)*u_Bend(3)*nu+u_Bend(2)*s; ...
u_Bend(1)*u_Bend(2)*nu+u_Bend(3)*s, u_Bend(2)*u_Bend(2)*nu+c, u_Bend(2)*u_Bend(3)*nu-u_Bend(1)*s; ...
u_Bend(1)*u_Bend(3)*nu-u_Bend(2)*s, u_Bend(2)*u_Bend(3)*nu+u_Bend(1)*s, u_Bend(3)*u_Bend(3)*nu+c];
d1 = R*d1p;
d2 = R*d2p;
d3 = R*d3p;
%find points on the midplane between the basal and distal plates
p1 = (d1+[0;rev_Dist; 0])/2;
p2 = (d2+[rev_Dist*cos(30);-1*rev_Dist*sin(30);0])/2;
p3 = (d3+[-1*rev_Dist*cos(30);-1*rev_Dist*sin(30);0])/2;
%find the midplane equation using those points
N = cross((p2-p1), (p3-p1)); %set of first three plane coefficients
D = -1*dot(N, p1);
midplane = [N; D];
%Find equations of the 3 planes that the basal arms revolve in
%--arm 1--
b1_1= [0;rev_Dist;0];%position of basal revolute
b1_2= [0;0;0];%center of basal plate
b1_3= [0;rev_Dist;1];%one unit above basal revolute
Nb1 = cross((b1_2-b1_1), (b1_3-b1_1));
Db1 = -1*dot(Nb1, b1_1);
cplane1 = [Nb1; Db1];
%--arm 2--
b2_1= [rev_Dist*cos(30);-1*rev_Dist*sin(30);0];%position of basal revolute
b2_2= [0;0;0];%center of basal plate
b2_3= [rev_Dist*cos(30);-1*rev_Dist*sin(30);1];%one unit above basal revolute
Nb2 = cross((b2_2-b2_1), (b2_3-b2_1));
Db2 = -1*dot(Nb2, b2_1);
cplane2 = [Nb2; Db2];
%--arm 3--
b3_1= [-1*rev_Dist*cos(30);-1*rev_Dist*sin(30);0];%position of basal revolute
b3_2= [0;0;0];%center of basal plate
b3_3= [-1*rev_Dist*cos(30);-1*rev_Dist*sin(30);1];%one unit above basal revolute
Nb3 = cross((b3_2-b3_1), (b3_3-b3_1));
Db3 = -1*dot(Nb3, b3_1);
cplane3 = [Nb3; Db3];
%Solve for the 3 intersection points of the basal and distal arms
%solution is obtained from the intersection of the midplane, armplane and
%the circle that the end of the basal arm traces
%-----------------------------------------------------------------------------
function F = plane1(x1)
F(1) = x1(1)*cplane1(1)+x1(2)*cplane1(2)+x1(3)*cplane1(3)+cplane1(4);
F(2) = x1(1)*midplane(1)+x1(2)*midplane(2)+x1(3)*midplane(3)+midplane(4);
F(3) = (x1(1)-b1_1(1))^2+(x1(2)-b1_1(2))^2+(x1(3)-b1_1(3))^2-arm_L^2;
end
fun1 = @plane1;
x0_1 = [0,0,0];
POI1 = fsolve(fun1,x0_1);
%------------------------------------------------------------------------------
function F = plane2(x1)
F(1) = x1(1)*cplane2(1)+x1(2)*cplane2(2)+x1(3)*cplane2(3)+cplane2(4);
F(2) = x1(1)*midplane(1)+x1(2)*midplane(2)+x1(3)*midplane(3)+midplane(4);
F(3) = (x1(1)-b2_1(1))^2+(x1(2)-b2_1(2))^2+(x1(3)-b2_1(3))^2-arm_L^2;
end
fun2 = @plane2;
x0_2 = [0,0,0];
POI2 = fsolve(fun2,x0_2);
%-------------------------------------------------------------------------------
function F = plane3(x1)
F(1) = x1(1)*cplane3(1)+x1(2)*cplane3(2)+x1(3)*cplane3(3)+cplane3(4);
F(2) = x1(1)*midplane(1)+x1(2)*midplane(2)+x1(3)*midplane(3)+midplane(4);
F(3) = (x1(1)-b3_1(1))^2+(x1(2)-b3_1(2))^2+(x1(3)-b3_1(3))^2-arm_L^2;
end
fun3 = @plane3;
x0_3 = [0,0,0];
POI3 = fsolve(fun3,x0_3);
%--------------------------------------------------------------------------------
%there will be 2 solutions for each point corresponding to bending in and
%bending out. We need to filter these to just bending out.
m1=[max(POI1(1)); max(POI1(2)); max(POI1(3))];
m2=[max(POI2(1)); max(POI2(2)); max(POI2(3))];
m3=[max(POI3(1)); max(POI3(2)); max(POI3(3))];
%with midplane points, find turning angles of basal joints
q=[0;0;1];%q is a reference vector to measure theta from. Vertical reference was chosen here
%Find turning angle using the dot product of the basal arm vector and the
%reference vector
theta1=eval(acos(dot(m1-b1_1, q)/norm(m1-b1_1)));
theta2=eval(acos(dot(m2-b2_1, q)/norm(m2-b2_1)));
theta3=eval(acos(dot(m3-b3_1, q)/norm(m3-b3_1)));
thetadeg = (180/pi).*[theta1; theta2; theta3];
block.Dwork(1).Data = thetadeg(1);
block.Dwork(2).Data = thetadeg(2);
block.Dwork(3).Data = thetadeg(3);
end Update
%%
%% Terminate:
%% Functionality : Called at the end of simulation for cleanup
%% Required : Yes
%% C-MEX counterpart: mdlTerminate
%%
function Terminate(block)
end Terminate
end