Target Language Compiler | ![]() ![]() |
Derivatives Function
The Outputs
and InitializeConditions
functions in this TLC file roughly parallel the corresponding functions in the sisosf.c
program and thus will not be elaborated on. The heart of the program is again the Derivatives
function, where the derivatives of the states (assigned to the dx
vector) will be computed. Since the expression for the derivatives for all but the last state is similar, it is put in a loop. However, the discrepancy in the indices of dx
and x
must be treated with care.
The main section of the Derivatives
function appears inside the %roll...%endroll
construct. The utility of this method as opposed to, say, foreach
, is that if there are only a few states (less than RollThreshold
, which is set to 5 by default), the expressions are explicitly written out, since using a for
loop would cause unnecessary overhead. However, when there are more states (especially when there are very many), the code is put in a for
loop. The %roll
command is explained in the Compiler Directives section of this document. However, this section points out some features as well.
The states run from 0
to (ncStates -1
), and therefore, so do the derivatives. However, when the dx
vector is returned by the call to the ssGetdX
macro, the pointer for the entire set of derivatives is returned, not just the ones corresponding to this block. In fact, this model has been designed so that the derivatives from the dx
block appear before those from the SiSoSF
block in the generated code. Therefore, dx
corresponding to x0 is actually dx[8]
in this example. For this purpose, we use the statement
%assign offset = ContStates[1]
in the beginning of the function. Alternatively, dx
could have been declared as
real_T *dx = ssGetdX(%<tSimStruct>) + offset;
and then the offset term could have been dropped, since dx[0]
would correspond to x0.
Next, since dx[ncStates - 1]
needs special treatment, the looping is done over the range [0 : ncStates - 2]
. This appears in the %roll
statement, reproduced here for convenience
%roll xIdx = [0:%<ncStates-2>], xlcv = RollThreshold, block, "Roller", rollVars
Parameters
The parameters are as follows: xIdx
plays a dual role. If the loop does roll, i.e., a for
loop is generated, then xIdx
is set to the first value of the RollRegion
(in this case 0). The for
loop always starts from zero and goes up to one less than the width of the RollRegion
. The RollRegion
, which usually (but not in this case) is set to the eponymous identifier from the model
.rtw
file, contains the vector(s) upon which the TLC compiler bases its decision whether or not to roll.
In this case, we have a customized vector, i.e., [0:%<ncStates-2>]
as our RollRegion
, and the xlcv
variable is set to the (string) value of the loop index. The parameter rollVars
specifies the variables over which the rolling takes place. If rolling does occur, a vector that starts from the appropriate place in (say) the state vector will be declared; similarly for the parameter vector. The "appropriate place" will be given by the value of xIdx
.
If the loop does not roll, xIdx
goes from 0 to one less than the width of the RollRegion
, irrespective of the actual start and end points of the vector. In this mode, the %roll
command behaves identically to the %foreach
command. However, the RollVars
are appropriately offset so that the correct elements of the state and parameter vectors (in this case) are used. This is given by the first element of the RollRegion
.
As an exercise, generate the code using the Build command in the Simulation Parameters dialog box. Check that the Loop rolling threshold option is set to 5
(less than the width of the RollRegion
) in the Options section of the dialog box.
Study the following lines of code from the Derivatives
function of the sisosf.tlc
file to see how they change. This gives important insights into the functionality of %roll
.
/* offset = %<offset> ncStates = %<ncStates> */ /* xIdx = %<xIdx> xlcv = %<xlcv> lcv = %<lcv>*/
Now, set the Loop rolling threshold to 10 so that the code does not roll. Study the code again, and see how the various parameters have changed.
Additional Exercise
gain.tlc
from matlabroot
/rtw/c/tlc
to your working directory.RollRegions
in the lines below to arbitrary vectors, e.g., [0:10,11,12,13:19]
.simple_mimo2.mdl
model from an earlier assignment, only changing the inputs to [1:20]
(to match our RollRegion
), and the gain to [20:-1:1]
to match the inputs.gain.tlc
is given below.sigIdx
, lcv
, etc. become.RollRegions
below to [0:10,11,12,13:19]
%roll sigIdx = RollRegions, lcv = RollThreshold, block, "Roller", rollVars %assign y = LibBlockOutputSignal(0, "", lcv, sigIdx) %assign u = LibBlockInputSignal(0, "", lcv, sigIdx) %assign k = LibBlockParameter(Gain, "", lcv, sigIdx) <snip
>Insert comment lines here before %endroll %endroll
This is not, of course, a recommended practice for writing TLC files (i.e., hard coding roll regions), but is merely an exercise to see how %roll
works. You may also try changing the RollRegion
to [3:10,. . .]
etc., and sigIdx
to sigIdx-1
in the %assign u
line.
When you are done, do not forget to change the name of gain.tlc
to gain_old.tlc
so that future code generation endeavors involving the Gain block are not hampered.
![]() | Generating Code for Models with States | Simulink External Mode and GRT | ![]() |