remove agent from assembler delay part - anylogic

I have a problem to manually remove/delete the agents from my assembler block (delay part). I would like to remove/delete the agents in the assembler with the click of a button. I think the problem is that remove() only removes the agents in the queue part of the assembler and not of the delay part right?
The "Reset" button should remove all agents from the two queue blocks and the assembler block.
I wrote the following code in the action of the button. Unfortunately the if condition doesn't work. Nevertheless, the agent remains in the delay part of the assembler. Does anyone have a solution suggestion for me?
while(Lager_Oberteile.size() > 0) {
Agent agent = Lager_Oberteile.removeFirst();
}
while(Lager_Plättchen.size() > 0) {
Agent agent = Lager_Plättchen.removeFirst();
}
if (Klebestation.delaySize() == 1) {
Klebestation.remove(Oberteil_Plättchen_geklebt) ;
}
offene_Aufträge = 0;
Thanks.

First you need to know what agent is in the delay of the assember, one way is to do this:
Agent a=assembler.delayGet(0); //the first agent in the delay
assembler.remove(a);
Done

Another way is to access the Delay within the service within the assembler (these are nested blocks essentially) and remove the agent from the delay:
So to remove the oldest agent in the assembler's delay, you can use
myAssemblerBlock.service.delay.stopDelay(agent);

Related

wait.free() is freeing multiple agents instead of 1

I currently have an event that is checked every 30 minutes and calls the function, which is used to check if conditions are met to free an agent Patientthat is in wait1
The event uses the code below and theoretically causes all of the agents in the wait1 to be checked.:
if (wait1.size() > 0){
for (int i = 0; i < wait1.size(); i++)
function(wait1.get(i));}
The function is seen below:
The problem is that although patient should theoretically only go from the wait1 block to the selectOutput3and eventually a seize if they satisfy one of the conditions in the function, it happens that if multiple patient satisfy the same condition, they both get free'd. However, there is only 1 SurgeonMorning and 1 SurgeonAfternoon, so once a patient is freed from the wait, it should seize the surgeon and not allow any of the other patients to be freed.
Yes, this happens because of the order of things happen
Anylogic first does the loop through all the agents in your wait block, and during the loop, the surgeon hasn't been seized yet so idle is always equal to true for all the agents in the wait block
you could so something like this
if (wait1.size() > 0){
for (int i = 0; i < wait1.size(); i++){
if(surgeonMorning.isReserved==false){
surgeonMorning.isReserved=true;
function(wait1.get(i));
}
}
}
then on the release, you can do surgeonMorning.isReserved=false when the time comes.
Nevertheless, your whole model could just be replaced by 1 service block from what I see. You are overdoing the amount of code needed.

How to set agents hight in delay block?

By seizeTransporter block my AGV seizes an agent called "Sitz" and transports it via Move by Transporter block to a Delay Block.
When AGV enters the delay block the transported agent "Sitz" is changing its cargo location to 0.
I tried to fix that issue with creating an parameter on main called p_assemblyHight with default value 1.0 and the following code in Actions section of the delay Block: agent.setHight(p_assemblyHight, METER);
Anyway this action will not execute.
What can I do so that my transported product (called "Sitz") stays on the agv and not dropping in delay block?
Check the two screenshots for better understanding.
Thank you a lot!
The setHeight method does not change the z-component, but the height of an agent presentation. Irrelevant for you.
You need to access your Sitz in the delay block and change its z-component.
In the Delay block call:
agent.setXYZ(agent.getX(), agent.getY(), 10);
The last argument is the Z component, adjust as needed. The first 2 just make sure the XY components are not changed

Anylogic: Queue TimeOut blocks flow

I have a pretty simple Anylogic DE model where POs are launched regularly, and a certain amount of material gets to the incoming Queue in one shot (See Sample Picture below). Then the Manufacturing process starts using that material at a regular rate, but I want to check if the material in the queue gets outdated, so I'm using the TimeOut option of that queue, in order to scrap the outdated material (older than 40wks).
The problem is that every time that some material gets scrapped through this Timeout exit, the downstream Manufacturing process "stops" pulling more material, instead of continuing, and it does not get restarted until a new batch of material gets received into the Queue.
What am I doing wrong here? Thanks a lot in advance!!
Kindest regards
Your situation is interesting because there doesn't seem to be anything wrong with what you're doing. So even though what you are doing seems to be correct, I will provide you with a workaround. Instead of the Queue block, use a Wait block. You can assign a timeout and link the timeout port just like you did for the queue (seem image at the end of the answer).
In the On Enter field of the wait block (which I will assume is named Fridge), write the following code:
if( MFG.size() < MFG.capacity ) {
self.free(agent);
}
In the On Enter of MFG block write the following:
if( self.size() < self.capacity && Fridge.size() > 0 ) {
Fridge.free(Fridge.get(0));
}
And finally, in the On Exit of your MFG block write the following:
if( Fridge.size() > 0 ) {
Fridge.free(Fridge.get(0));
}
What we are doing in the above, is we are manually pushing the agents. Each time an agent is processed, the model checks if there is capacity to send more, if yes, a new agent is sent.
I know this is an unpleasant workaround, but it provides you with a solution until AnyLogic support can figure it out.

Anylogic: Queue timeout & condition

In the default settings it is possible to set a time in the queue after which an agent leaves the queue via outTimeOut. However, only a fixed time can be entered in the corresponding field, e.g. 12 hours. Is there a possibility to link these 12 hours with a condition? In my case, the agent should only leave the queue after 12 hours via outTimeOut if a certain condition is also met. In my case, if a variable varIN == 1.
Collect the time in queue statistics for each agent. Create a parameter called entryTime. When they enter the block, set agent.entryTime=time();
You can create an event that iterates through the queue every 1 second and removes the agents that meet your conditions from the queue (by using remove(Agent agent) function). That means if (time()-agent.entryTime>12)&&(agent.varIN==1), you will remove that agent.
Loop will look like this:
for (int i=0; i< yourQueue.size(); i++) {
YourAgentType currentAgent = ((YourAgentType)yourQueue.get(i));
if ((time()-currentAgent.entryTime>12)&&(currentAgent.varIN==1)){
yourQueue.remove(currentAgent);
}
}
You can use a function (returning a double) to define and calculate the most complex logic you like. If you provide an argument of type Agent (or the specific agent type flowing through the blocks), it can even account for your agent characteristics.
In the queue block timeout, simply call the function.

How to stop source blocks when rackSystem if full

i saw a previous question about something like my issue but i couldn't make it work as suggested in the answer.
I have 5 sources that generate 5 different agents to be stored via a rackStore block in a rackSystem; a resource from a resource pool pick them up (rackPick block) and give them to an assembler. At some point i seize the same resource to do other tasks but the simulation is interrupted when the rack is full. I tried to make the sources stop when the rack is full in this way:
if( rackSystem.isFree(1, 1, 1) == false)
self.set_rate(0);
I typed this code in each source "on exit" bar but it doesn't work; what am i missing?
The rackSystem is made of 5 different palletRack blocks, each with 1 row/position/level.
Thanks for your advices.
You are only checking if the position (0,0,0) is free. Instead, amend your condition to this:
if( rackSystem.hasSpace() == false) self.set_rate(0);