I'm working on a NetLogo model that has a great deal of information stored in lookup tables and embedded in patches that affect agent behavior. As a result, I'm creating a model "reset" from an extension that clears the turtles, and resets the timer and ticks.
I would also like to have the extension reset specific globals that track model results, but not reset all of the globals that are constants (look up tables of precomputed information). I would also like to reset all the interface plots.
Any thoughts on how to go about this?
I apologize for no code to show, as is the case I can't show what is not working because I'm not even sure what to try!
NetLogo engine internals aren't really documented except in a general way at https://github.com/NetLogo/NetLogo/wiki/Engine-architecture, so if your extension wants to manipulate engine stuff directly, you'll usually have to consult the NetLogo source code to learn specifics of how it's done.
You want something like clear-globals, so check out https://github.com/NetLogo/NetLogo/blob/5.x/src/main/org/nlogo/prim/etc/_clearglobals.scala and https://github.com/NetLogo/NetLogo/blob/37cc1a0aa371c11e89f5b39b5143ed5d951e6081/src/main/org/nlogo/agent/World.java#L849-L866.
You want something like clear-all-plots, so check out https://github.com/NetLogo/NetLogo/blob/37cc1a0aa371c11e89f5b39b5143ed5d951e6081/src/main/org/nlogo/prim/plot/primitives.scala#L45-L50 and https://github.com/NetLogo/NetLogo/blob/37cc1a0aa371c11e89f5b39b5143ed5d951e6081/src/main/org/nlogo/plot/PlotManager.scala#L54-L57.
And so on.
EDIT:
For access to the PlotManager, note that plot/primitives.scala has:
workspace.plotManager.asInstanceOf[PlotManager]
in Java code on an extension, from the workspace plotManager() gets you the PlotManager, except the return type of that method is Object (yes, I know, it's grungy and horrible), so you need to insert a typecast to org.nlogo.plot.PlotManager and you're good to go. PlotManager has methods for getting to particular plots.
Related
Is there an easy way to figure out all places where a variable or parameter is being utilised in annylogic. Trying to locate where each variable is used can be a pain during debugging.
Sure. Just "ignore" it in the properties and compile the model.
You will get a list of errors for all places where it is called. Double-click on each error and AnyLogic even takes you there :)
Else, you can also use the AnyLogic search functionality.
in order to get some relief for that pain if your model is too big, all your variables should be private and you create setters, so each time you change your variable, you required to use a set function.
This doesn't solve your question, but it tells you what to do in future models to make it easier for you
check this video
https://www.youtube.com/watch?v=gNBfdB6YF7o
Roald has written an excellent guide for the Twincat Eventlogger.
https://roald87.github.io/twincat/2020/11/03/twincat-eventlogger-plc-part.html
https://roald87.github.io/twincat/2021/01/20/twincat-eventlogger-hmi-part.html
For us this is exactly what we want, there is however 1 thing I haven't figured out. How to get the sourcename of the alarm in multiple languages in the HMI. params::sourceName gives the path in the software (example: MAIN.fbConveyor1.Cylinder1) This path can be customized when initializing the alarm (as Roald has shown). This doesn't work in my case, since I would like to define a generic alarm (example: "Cilinder not retracted within maximum time") that is instantiated multiple times.
I was thinking of using the source as a way to show the operator where the alarm occurs. We use this way (path) already for saving machine settings among other things. The machines we build are installed all over the world, so multilanguage is a must.
Beckhoff does support multilanguage alarm names (when defined), but the source is not defined, but dynamically generated.
Anyone have an idea how this problem can be solved?
If I understand your question correctly, then being able to parameterize the event text with information of the source of the problem should help you out.
If you define the event text as Cylinder {0} has not retracted in time. then you can add the arguments of that text during runtime.
IF bRaiseAlarm THEN
bRaiseAlarm := FALSE;
fbAlarm.ipArguments.Clear().AddString('Alice');
fbAlarm.Raise(0);
END_IF
However, since this also stated in the articles you mentioned, I am unsure if this would solve your problem.
'Alice' in this example, can be hard to localize. The following options come to my mind.
The string can be based on an ENUM. Enums can have textlist support, so if you add your translations there, that should allow multilingual output. However... this does require a lot of setup, placing translations inside your code, and making sure the PLC application is aware of the language that the parameter should use.
Use tags to mark the source device, as tags can be language invariant. It is not the most user-friendly method, but it could work for you. It would become something like: "Cylinder 'AA.1123' did not retract in time.". 'AA.1123' as a tag would have to be stored inside your PLC code as a string. You will have to trust that your operator can relate the tag back to the actual source.
Hopefully, this helped, or else please help me understand the problem better.
As a part of my studies, I am interested in modifying some constant properties of a medium like water. For example, in Buildings.Media.Water that cannot be accessed by Dymola (I opened it in Visual Studio Code), I am going to change a constant e.g. density. Is there any way to do so? or should I do it through partial medium?
This question is also applied to some thermo-physical properties like thermal diffusivity that I could not find it in the constants of water.
I would be thankful for your advise.
In Dymola you should be able to modify constants if you double-click the package containing the constant(s) and then edit the text using the Modelica-Text view. This way you should be able to edit all constants in the package. Obviously write-access is required to do so (which you e.g. don't usually have for the MSL).
Using inheritance (partial medium) makes sense if you want to be able to switch between multiple media quickly or you don't have write access. For experimentation it should be fine to directly change values - being careful not to forget to revert...
Regarding the thermal diffusivity: it probably simply is not there. You could inherit from the original package and add it if that is the best solution to your needs.
I am using Behavior Search to calibrate my NetLogo model for 20 different hospital units. I am using global variables to set the min and max for several sliders in my model, but I think this is causing an error in Behavior Search when I attempt to load the parameter values from the model. However, I don't want to manually enter these parameter ranges manually each time I use Behavior Search.
Is there a way to get around this error? Is there a way to set the min and max for a specific slider to a constant, rather than using global variables?
Thanks for your help!
BehaviorSearch developer here -- if I'm understanding your question correctly, your NetLogo model has a slider which has a min/max constraint that is not set to a constant, but is instead set to a global variable (in the slider settings, accessed from the NetLogo interface).
When I choose such a model using the BehaviorSearch GUI, and then click the "Load parameter ranges from model interface" button, then I get the value of 0 for that constraint. (I don't see any error message -- just the value 0 (if you're getting an error message instead, then I may not be understanding your situation correctly, and perhaps you could post exactly what error message you're seeing?)
This will be true even if you are setting the slider min/max to a global value in the special STARTUP procedure (see: http://ccl.northwestern.edu/netlogo/docs/dict/startup.html), because STARTUP is only run when a model loads in the NetLogo GUI, and not when a model is loaded in headless NetLogo.
Thus, unfortunately, I think the answer to your question is: "no, there isn't a way to get BehaviorSearch to load the parameter ranges from global variables within the model".
Some possible work-arounds:
BehaviorSearch is open-source -- some changes could be made to it -- i.e., maybe adding in a call to "startup" whenever BehaviorSearch GUI loads the parameter ranges would be sufficient for you.
If you're only doing a few searches, I don't see why manually editing the parameter ranges would be particularly onerous. However, if you're generating a lot of different searches with this model, then I can see how it might be an issue. The .bsearch files are just XML text files, so you might consider generating them without the BehaviorSearch GUI, e.g. using a scripting language.
Do you use table-of-contents for listing all the functions (and maybe variables) of a class in the beginning of big source code file? I know that alternative to that kind of listing would be to split up big files into smaller classes/files, so that their class declaration would be self-explanatory enough.. but some complex tasks require a lot of code. I'm not sure is it really worth it spending your time subdividing implementation into multiple of files? Or is it ok to create an index-listing additionally to the class/interface declaration?
EDIT:
To better illustrate how I use table-of-contents this is an example from my hobby project. It's actually not listing functions, but code blocks inside a function.. but you can probably get the idea anyway..
/*
CONTENTS
Order_mouse_from_to_points
Lines_intersecting_with_upper_point
Lines_intersecting_with_both_points
Lines_not_intersecting
Lines_intersecting_bottom_points
Update_intersection_range_indices
Rough_method
Normal_method
First_selected_item
Last_selected_item
Other_selected_item
*/
void SelectionManager::FindSelection()
{
// Order_mouse_from_to_points
...
// Lines_intersecting_with_upper_point
...
// Lines_intersecting_with_both_points
...
// Lines_not_intersecting
...
// Lines_intersecting_bottom_points
...
// Update_intersection_range_indices
for(...)
{
// Rough_method
....
// Normal_method
if(...)
{
// First_selected_item
...
// Last_selected_item
...
// Other_selected_item
...
}
}
}
Notice that index-items don't have spaces. Because of this I can click on one them and press F4 to jump to the item-usage, and F2 to jump back (simple visual studio find-next/prevous-shortcuts).
EDIT:
Another alternative solution to this indexing is using collapsed c# regions. You can configure visual studio to show only region names and hide all the code. Of course keyboard support for that source code navigation is pretty cumbersome...
I know that alternative to that kind of listing would be to split up big files into smaller classes/files, so that their class declaration would be self-explanatory enough.
Correct.
but some complex tasks require a lot of code
Incorrect. While a "lot" of code be required, long runs of code (over 25 lines) are a really bad idea.
actually not listing functions, but code blocks inside a function
Worse. A function that needs a table of contents must be decomposed into smaller functions.
I'm not sure is it really worth it spending your time subdividing implementation into multiple of files?
It is absolutely mandatory that you split things into smaller files. The folks that maintain, adapt and reuse your code need all the help they can get.
is it ok to create an index-listing additionally to the class/interface declaration?
No.
If you have to resort to this kind of trick, it's too big.
Also, many languages have tools to generate API docs from the code. Java, Python, C, C++ have documentation tools. Even with Javadoc, epydoc or Doxygen you still have to design things so that they are broken into intellectually manageable pieces.
Make things simpler.
Use a tool to create an index.
If you create a big index you'll have to maintain it as you change your code. Most modern IDEs create list of class members anyway. it seems like a waste of time to create such index.
I would never ever do this sort of busy-work in my code. The most I would do manually is insert a few lines at the top of the file/class explaining what this module did and how it is intended to be used.
If a list of methods and their interfaces would be useful, I generate them automatically, through a tool such as Doxygen.
I've done things like this. Not whole tables of contents, but a similar principle -- just ad-hoc links between comments and the exact piece of code in question. Also to link pieces of code that make the same simplifying assumptions that I suspect may need fixing up later.
You can use Visual Studio's task list to get a listing of certain types of comment. The format of the comments can be configured in Tools|Options, Environment\Task List. This isn't something I ended up using myself but it looks like it might help with navigating the code if you use this system a lot.
If you can split your method like that, you should probably write more methods. After this is done, you can use an IDE to give you the static call stack from the initial method.
EDIT: You can use Eclipse's 'Show Call Hierarchy' feature while programming.