setting sampling time in c mex s func - c

What is the equivalent of the following for a C-mex s function? That is, how do I set discrete sample time of a block to the top level fixed step size in C?
My problem is, I could not find a way to "get" the top level fixed step size parameter in C-mex.
function setup(block)
block.SampleTimes = [str2double(get_param(bdroot, 'FixedStep')) 0];

Use ssGetFixedStepSize to get the base rate of the model. You may also want to ssSetErrorStatus if the that call returns 0, because that means your model is not configured with a FixedStep solver.
If, for some reason, you really want to go about fetching the information similar to what you have in the question, then you might be able to get access to it if you dig through the SimStruct pointer's fields. To do this, breakpoint in the mex file using a debugger and watch that variable.
Another option would be a few mexCallMATLAB calls to get the information you want.

Related

How to use iddata type structure

I want to resample an array of elements using the command idresamp(). The input arguments for idresamp function is an array x. So I should get the output as an array. However, I am getting a structure iddata. I don't know how to access the elements /result of the resampling. Can somebody please show how to access the resampled values? Thank you.
x=rand(4000,1); %create some arbitrary data
x_resamp =idresamp(x,2); %resampling factor is 2
Here x_resamp is of iddata type. So, I am unable to access the result. On clicking the variable x_resamp this is what I got
How does one access the resampled values (output). Where is the array? The next step is to calculate the power after resampling and hence I need to use the resampled values.
I am using Matlab R2018a.
If you just want to resample by a factor 2, and have access to the Signal Processing Toolbox, use resample:
y = resample(x,2,1);
If you are insistent on using idresamp, you need to know that it returns an object of type iddata, which comes with a long documentation on usage. I think this complicates things more than you are looking for. It seems you should be able to do:
x_resamp = idresamp(x,2);
y = x_resamp.OutputData;
(but I can't test this because I don't have access to this toolbox.)

How to work around array of components with fixed size error?

I have a class with a port of dimensions [x,y] which is connected to another class having a matching port. Now I want to provide value to these variables [x,y] through external function call in which I basically read a .xml file and obtain values for x and y. But Dymola gives an error for this since during compilation it comes out as a non fixed size array.
Screenshot of error is attached.
The array sizes are structural parameters and they usually cannot depend on external function calls because they should be known at compile time. This is however supported in for example OpenModelica where a dll of the external function is built and called and the results are fetched during model compilation.
The only way to support this in all tools is to generate the model using an external tool which reads the xml and changes the .mo file with the values read.
You could probably have something like Parameters.mo:
package Parameters
constant Integer nTube = <EXTERN_NTUBE>;
constant Integer nSeg = <EXTERN_NSEG>;
end Parameters;
and your external tool will read the XML and bind and in Parameters.mo which you can then use in your models via Parameters.nTube and Parameters.nSeg. Maybe it would be good to give some defaults so that it works to use this file directly:
package Parameters
constant Integer nTube = 1;
constant Integer nSeg = 2;
end Parameters;
and then your external tool will replace 1 and 2 with the needed values before compilation.
This should be improved in Dymola 2017 (without the need for modifying the Modelica code). In earlier versions of Dymola it should work if the you translate the C-functions called to compute nTube and nSeg.
If that does not help your complete code would be needed to analyze the problem.

Minimizing an array-returning function using "fminunc"

I am using MATLAB to build a code that does automatic tuning of the three PID controller gains. The way I am thinking of it, is to minimize the error (the difference between the desired state and the obtained one) of my system, for that, I coded a function that accepts the PID gains as input parameters and returns the calculated error, namely:
errors_vector = closedLoopSimulation(pidGains)
Since I have three set points (input commands), then the dimension of the output errors_vector is 3*N, where N is the number of time samples I have (1000 in my case). So that is the function I want to minimize, and for doing so, I tried using fminunc command, namely:
pidGains_ini = [2.4 0.1 0.4];
func = #closedLoopSimulation;
[pid, fval] = fminunc(func, pidGains_ini)
However, when I run the last piece of code, I get this error:
User supplied objective function must return a scalar value.
which is clearly due to the fact that that errors_vector is a 3*1000 array and not a scalar.
My questions would be, from the programming point of view, is there a way that I can make fminunc minimize functions that return arrays?
On the other hand, and from the Control Theory point of view, is there another way which I can optimize the PID gains automatically?
I hope I made myself clear enough.
Thanks
Minimizing a vector is not very well defined (there is something called multi-objective or multi-criteria optimization but that is somewhat specialized). "Normal" optimization methods can only minimize (or maximize) scalar objectives. I suspect in your case you could form such an objective by taking the sum of the squared errors and minimize that. To be complete: this is standard operating procedure and is often called "least squares".

SIMULINK Holding Previous Value of a Signal

I am trying to implement a pulse generator in SIMULINK that needs to know the previous 2 input values i.e. I need to know the previous 2 state values for the input signal. Also, I need to know the previous output value.
My pseudo code is:
IF !input AND input_prevValue AND !input_prevValue2
output = !output_pv
ELSE
output = output_pv;
I know that I can use legacy function importer and use C code to do this job in SIMULINK. However, the problem arises when you apply a configuration reference set to your model. The key problem is the flexibility. When you use this model somewhere else (say share it with a colleague or whoever), unless you have used a configuration reference set, you can rebuild the code (i.e. from S-Function Block) and run your model. But you cannot rebuild the code if the configuration reference set is applied.
My solution would be to implement the logic in a way that I can do the same without C functions. I tried to use the memory block in SIMULINK but apparently it doesn't do it. Does anyone know how to hold previous values for input and output in SIMULINK (for as long as the model is open)?
Have you tried with a MATLAB Function block? Alternatively, if you have a Stateflow license, this would lend itself nicely to a state chart.
EDIT
Based on your pseudo-code, I would expect the code in the MATLAB Function block to look like this
function op = logic_fcn(ip,ip_prev,ip_prev2,op_prev)
% #codegen
if ~ip && ip_prev && ~ip_prev2
op = ~op_prev;
else
op = op_prev;
end
where ip, ip_prev, ip_prev2 and op_prev are defined as boolean inputs and op as a boolean output. If you are using a fixed-step discrete solver, the memory block should work so that you would for example feed the output of the MATLAB Function block to a memory block (with the correct sample time), and the output of the memory block to the op_prev input of the MATLAB Function block.
You could (and should) test your function in MATLAB first (and/or a test Simulink model) to make sure it works and produces the output you expect for a given input.
This is reasonably straight forward to do with fundamental blocks,
Note that for the Switch block the "Criteria for passing first input:" has been changed to "u2~=0".

Arrays in PowerBuilder

I have this code
n_userobject inv_userobject[]
For i = 1 to dw_1.Rowcount()
inv_userobject[i] = create n_userobject
.
.
.
NEXT
dw_1.rowcount() returns only 210 rows. Its so odd that in the range of 170 up, the application stop and crashes on inv_userobject[i] = create n_userobject.
My question, is there any limit on array or userobject declaration using arrays?
I already try destroying it after the loop so as to check if that will be a possible solution, but it is still crashing.
Or how can i be able to somehow refresh the userobject?
Or is there anyone out there encounter this?
Thanks for all your help.
First, your memory problem. You're definitely not running into an array limit. If I was to take a guess, one of the instance variables in n_userobject isn't being cleaned up properly (i.e. pointing to a class that isn't being destroyed when the parent class is destroyed) or pointing to a class that similarly doesn't clean itself up. If you've got PB Enterprise, I'd do a profiling trace with a smaller loop and see what is being garbage collected (there's a utility called CDMatch that really helps this process).
Secondly, let's face it, you're just doing this to avoid writing a reset method. Even if you get this functional, it will never be as efficient as writing your own reset method and reusing the same instance over again. Yes, it's another method you'll have to maintain whenever the instance variable list changes or the defaults change, but you'll easily gain that back in performance.
Good luck,
Terry.
I'm assuming the crash you're facing is at the PBVM level, and not a regular PB exception (which you can catch in your code). If I'm wrong, please add the exception details.
A loop of 170-210 iterations really isn't a large one. However, crashes within loops are usually the result of resource exhaustion. What we usually do in long loops is call GarbageCollect() occasionally. How often should it be called depends on what your code does - using it frequently could allow the use of less memory, but it will slow down the run. Read this for more.
If this doesn't help, make sure the error does not come from some non-PB code (imported DLL or so). You can check the stack trace during the crash to see the exception's origin.
Lastly, if you're supported by Sybase (or a local representative), you can send them a crash dump. They can analyze it, and see if it's a bug in PB, and if so, let you know when it was (or will be) fixed.
What I would normally do with a DataWindow is to create an object that processes the data in a row and call it for each row.
the only suggestion i have for this is to remove the rowcount from the for (For i = 1 to dw_1.Rowcount()) this will cause the code to recount the rows every time it uses one. get the count into a variable and then use the variable. it should run a bit better and be far more easy to debug.

Resources