Hello: I am working on model that adds an agent to a user specified location in main. To keep it simple, the agent is MyBox. I have a button control in main that does the following.
MyBox b = new MyBox();
b.createAndStart(this);
add_myBoxes();
b.rectangle.setFillColor(randomColor());
b.setXYZ(0, 0, zLoc);
zLoc += 20;
I stumbled on a solution, but before I added b.createAndStart(this), I kept getting a NullPointerException. Can someone please provide insight on what this method does? AnyLogic help says it assigns the owner of this agent to the top level agent of the model, which I am assuming is main in this case. Why is that necessary to do if I have added the agent to myBoxes population in main.
Typically, you do not use that function. The add_myBoxes(...) function does all that for you, so no need to use it at all.
So in your case, do not use it but ALSO do not use your custom creator new MyBox().
Simply use
MyBox b = add_myBoxes();
b.rectangle.setFillColor(randomColor());
b.setXYZ(0, 0, zLoc);
zLoc += 20;
and you are good to go
PS: AnyLogic allows you to use many functions that are neither documented nor self-explanatory. However, 99% of the cases you do not actually need them ;)
Related
I want my agent to be of a single type. Where type contains a list of 3 options. And the allotment should be based on probability. E.g. let's say I want to allot 1: 30%, 2: 50% and 3: 20% to each of the agents generated in the source of my main tab.
I tried with one of the ways by declaring th parameter as int and then writing randomTrue(0.3)?1:randomTrue(0.7)?2:3 in the default value. But every time the agent comes with the same value of 2.
Please can anyone help me with this??
And if I try to allot the parameters in the main window at any of the blocks, do they get attached to the specific agent that passes through that block or its value just gets updated for that time until the other agent passes? Actually I have to check each and every agent for the parameter and then send it through a specific output path from the selectoutput block.
Your code does not actually change anything in the created agent.
Create a parameter `myType´ of type Integer.
In your source code write:
agent.myType = randomTrue(0.3) ? 0 : randomTrue(0.7) ? 1 : 2
Make sure your Source block actually creates agents of the Agent type that holds the myType parameter.
Study some of the example models and tutorials, it is covered in many places :-)
I have a class with a simple user interface and want to write unit tests for all public member functions.
One of my buttons issues a warning via dialog. I use the uiconfirm function and assign the result to a variable to block the function until the user confirms the dialog.
classdef UI
properties
fig matlab.ui.Figure
button matlab.ui.control.Button
end
methods
function obj = UI()
obj.fig = uifigure();
obj.button = uibutton(obj.fig);
obj.button.Text = "click me";
obj.button.ButtonPushedFcn = #(~, ~) obj.click();
end
end
methods
function click(obj)
[~] = uiconfirm(obj.fig, "Something failed.", "Warning", ...
"Options", {'OK'}, "Icon", "warning");
end
end
end
I use class based unit tests:
https://de.mathworks.com/help/matlab/class-based-unit-tests.html
How can I test the click function?
I'm not quite sure if you're familiar with Matlab App Testing Framework. The App Testing Framework allows you to programmatically interact with appdesigner/uifigure apps. Take a look at the component-gesture availability matrix to help accelerate your UI Testing needs. Having said that, as of today, app testing framework doesn't yet support directly interacting with blocking UI Dialog's like uiconfirm.
An obvious brute force way of solving the blocking problem is to shadow the uiconfirm function in test with your custom version that could be non-blocking. If this is an easy enough acceptable solution for you, go forward with it. However, as your app changes and scales up, the mocks might need to get complicated too and thus become hard to maintain.
With that in mind, A better approach to test your app programmatically is to use a mocking framework to create a mock object to define the behavior of uiconfirm. The best way to achieve this is via Dependency Injection. In your case, the App could take/have a property that could store a context aware "UIConfirm [name it according to your workflow]" object . By default in a production environment, it would call the real uiconfirm command, but a “mock” or “stub” delegator could supply deterministic outputs to make the system more testable (and avoid the “blocking” dialog issue altogether) It’s certainly added overhead to do this in an otherwise simple App, but I get the sense that you value testing as much as we do!
Also please take a look at this detailed Mocking-App Testing example https://www.mathworks.com/help/matlab/matlab_prog/write-test-that-uses-app-testing-and-mocking-frameworks.html
the basic idea behind the modeling issue is a breakdown of a production machine.
I would like to model this by setting the arrival rate (simply arrivals per second) to zero (Source.rate = 0). After the machine is repaired, the arrival rate is set to its actual value again (e.g., Source.rate = 5). While the first command does the job, the second does not seem to have any effect, i.e. new agents are not created.
The segment of the model is rather simple: Source --> Select Output (decision about breakdown) --> true: go on in production; false: delay (repair machine) --> go on in production.
Source.rate = 0 is called at the out port (false) of "breakdown" and Source.rate = 5 at the out port of "repair".
https://i.stack.imgur.com/hqGoI.png
Of cause, this issue might be modeled differently (e.g., using hold with disabled "forced pushing"), however, it is not clear for me why my approach does not work.
Thanks in advance!
Instead of using source.rate=5; use source.set_rate(5);
To expand on Felipe's answer with an explanation:
Instead of using source.rate=5; use source.set_rate(5);
rate is effectively a Parameter (in the AnyLogic sense) of the Source block. (All AnyLogic's Process Modeling blocks are actually themselves Agents developed by AnyLogic, and thus with Parameters, Variables, etc.)
You can set an AnyLogic Parameter directly (via just assigning a value as you did), but they also all have a set_<parameter name> method (function) which should really always be used instead because this triggers any internal on-change logic for this Parameter. It is only this triggered logic (internal to the Source block) which causes the Source to 're-evaluate' the rate properly.
(You can use on-change logic for Parameters in your own models, and need to do so when altering a parameter requires some 'adjustments' to the rest of the model; i.e., in situations where the change doesn't 'just work' due to other bits of the model reading the new value after the change point.)
I don't know why your model doesn't work (maybe more details of your model is needed), but a simple solution which I tested and worked, is as below:
You can set the source's "Type of arrival" to "calls of inject() function", add an event to your model and set its "Trigger type" to "Rate" and set its rate value to 5. Then in action code of the event use below code:
if(yourCondition)
{
source.inject(1);
}
I hope it helps you.
I want to write a function that automatically changes the parameter SampleTime of all blocks in my model to a specific value. I can use find_system to find all blocks and then I can loop through all blocks and use set_param('Blockpath','SampleTime','0.001'). But if I do this and the block does not have a parameter called SampleTime, it'll make my program crash.
So my question is how can I find out if the parameter exists before setting it? I tried something like exist(['blockpath','/SampleTime']), but it didn't do what I expected. Any ideas?
You can use get_param('blockpath','ObjectParameters') to get a struct with all parameters and then use isfield to check if you can find SampleTime.
I think what you are doing is not a good idea. In typical simulink models, you have the sample time set only at very few places, running all other models with inherited sample time. In most cases, it is not a problem to change these few places.
If you have to many blocks or you frequently change the sample time, better use a workspace variable or a mask parameter. Set all blocks to to have sample time x and put x=0.01 in your base work space to set it for all blocks.
Building on #Daniel's answer, if you really must do this, which for reasons given in the comments to #Daniel's answer is a bad idea, then the simplest approach is
% Define the new value as a string
>> newSampleTime = '10';
% Find all blocks in the model
>> allBlocks = find_system(gcs);
% Identify the blocks that have a SampleTime property
>> blockIdx = cellfun(#(c)isfield(get_param(c,'ObjectParameters'),'SampleTime'),allBlocks);
% Change the sample time
>> cellfun(#(c)set_param(c,'SampleTime',newSampleTime),allBlocks(blockIdx));
I am currently working on a tool written in M-Script that executes a set of checks on a given simulink model. This tool does not compile/execute the model, I'm using find_system and get_param to retrieve all the information I need in order to run the routines of my tool.
I've reached a point where I need to determine whether a certain block has direct-feedthrough or not. I am not entirely sure how to do this. Two possible solutions come to mind:
A property might store this information and might be accessible via get_param. After investigating this, I could not find any such property.
Some block types have direct-feedthrough (Sum, Logic, ...), some other do not (Unit Delay, Integrator), so I could use the block type to determine whether a block has direct-feedthrough or not. Since I'm not an experienced Simulink modeller, I'm not sure if its possible to tell whether a block has direct-feedthrough by solely looking at its block type. Also, this would require a lookup table including all Simulink block types. An impossible task, since additional block types might get added to Simulink via third party modules.
Any help or pointers to possible solutions are greatly appreciated.
after some further research...
There is an "official solution" by Matlab:
just download the linked m-file
It shows that my idea was not that bad ;)
and for the record, my idea:
I think it's doable quite easily. I cannot present you some code yet, but I'll see what I can do. My idea is the following:
programatically create a new model
Add a Constant source block and a Terminator
add the Block you want to get to know the direct feedthrough ability in the middle
add_lines
run the simulation and log the states, which will give you the xout variable in the workspace.
If there is direct feedthrough the vector is empty, otherwise not.
probably you need to include some try/catch error catching for special cases
This way you can analyse a block for direct feedthrough by just migrating it to another model, without compiling your actual main model. It's not the fastest solution, but I can not imagine that performance matters that much for you.
Here we go, this script works fine for my examples:
function feedthrough = hasfeedthrough( input )
% get block path
blockinfo = find_system('simulink','Name',input);
blockpath = blockinfo{1};
% create new system
new_system('feed');
open_system('feed');
% add test model elements
src = add_block('simulink/Sources/Constant','feed/Constant');
src_ports = get_param(src,'PortHandles');
src_out = src_ports.Outport;
dest = add_block('simulink/Sinks/To Workspace','feed/simout');
dest_ports = get_param(dest,'PortHandles');
dest_in = dest_ports.Inport;
test = add_block(blockpath,'feed/test');
test_ports = get_param(test,'PortHandles');
test_in = test_ports.Inport;
test_out = test_ports.Outport;
add_line('feed',src_out,test_in);
add_line('feed',test_out,dest_in);
% setup simulation
set_param('feed','StopTime','0.1');
set_param('feed','Solver','ode3');
set_param('feed','FixedStep','0.05');
set_param('feed','SaveState','on');
% run simulation and get states
sim('feed');
% if condition for blocks like state space
feedthrough = isempty(xout);
if ~feedthrough
a = simout.data;
if ~any(a == xout);
feedthrough = ~feedthrough;
end
end
delete system
close_system('feed',1)
delete('feed');
end
When enter for example 'Gain' it will return 1, when you enter 'Integrator' it will return 0.
Execution time on my ancient machine is 1.3sec, not that bad.
Things you probably still have to do:
add another parameter, to define whether the block is continuous or discrete time and set the solver accordingly.
test some "extraordinary" blocks, maybe it's not working for everything. Also I haven implemented anything which could deal with logic, but actually the constant is 1 so it should work as well.
Just try out everything, at least it's a good base for you to work on.
A famous exception is the StateSpace Block which can have direct feedthrough AND states. But there are not sooo much standard blocks with this "behaviour". If you also have to deal with third party blocks you could get into some trouble, I have to admit that.
possible solution for the state space: if one compares xout with yout than one can find another indicator for direct feedthrough: if there is, the vectors are not equal. If so, than they are equal. Just an example, but I can imagine that it is possible to find more general ways to test things like that.
besides the added simout block above one needs the condition:
% if condition for blocks like state space
feedthrough = isempty(xout);
if ~feedthrough
a = simout.data;
if ~any(a == xout);
feedthrough = ~feedthrough;
end
end
From the documentation:
Tip
To determine if a block has direct feedthrough:
Double-click the
block. The block parameter dialog box opens.
Click the Help button in
the block parameter dialog box. The block reference page opens.
Scroll
to the Characteristics section of the block reference page, which
lists whether or not that block has direct feedthrough.
I couldn't find a programmatic equivalent though...
Based on a similar approach to the one by #thewaywewalk, you could set up a temporary model that contains an algebraic loop, similar to,
(Note that you would replace the State-Space block with any block that you want to test.)
Then set the diagnostics to error out if there is an algebraic loop,
If an error occurs when the model is compiled
>> modelname([],[],[],'compile');
(and you should check that it is the Algebraic Loop error that has occured), then the block has direct feed though.
If no error occurs then the block does not have direct feed though.
At this point you would need to terminate the model using
>> modelname([],[],[],'term');
If the block has multiple inports or outprts then you'll need to iterate over all combinations of them.