Error in deleteSelf(): Agent should belong to some population - anylogic

I have the following model where I have a pallet agent and a box agent with a population of boxes inside the pallet agent. So pallets arrive then a forklift moves them to a table and then they enter the "delay" block that takes it to the entrance block of the Box Process. In the bottom, flowchart forklifts remove boxes from the pallets and move them to a node as shown in the picture. Once all the boxes have been removed from a pallet, a forklift takes the pallets out and they get sunk.
Currently, the removed boxes are added to a queue and they stay there. I want to remove/destroy them with a sink. When I add a sink instead of/ or after the queue I get the following error
Exception during discrete event execution:
root.pallets[0].boxes[-1]:
Error in deleteSelf(): Agent should belong to some population
java.lang.RuntimeException: root.pallets[0].boxes[-1]:
Error in deleteSelf(): Agent should belong to some population
Is there a way to get around this error. I remove the boxes from the pallets in a statechart inside the pallet agent that loops until all the boxes are removed:
if (boxes.size() > 0){
Box b = boxes(0);
b.box_location = this.getXYZ();
remove_boxes(b);
get_Main().enter.take(b);
current_N_Boxes--;}
Thank you!

Agents flowing through a process must exist inside a population. You are removing the boxes from their population (inside the pallet agent) before trying to delete them, hence the error.
There are several ways to handle this:
Use Batch/Unbatch or Pickup/Dropoff blocks to 'properly' have agents inside agents with both parents and childs moving through processes at different times. (AnyLogic handles having the unbatched/dropped-off agents still existing in the default population.)
Create your box agents inside a master population in Main, and use collections in your pallet agents to refer to the boxes inside them. Then you can 'remove' them from the pallet (by removing them from the pallet's collection) whilst keeping them in the master population until they end their part of the process.
Move your box agents to a population in Main (say unpalettedBoxes) when removing them from the pallet (use the goToPopulation function in the box agent) and proceed as in 2.

Related

A question about seizing more than one ressource in Anylogic

I'm working on a supply chain project with AnyLogic. In my model which is similar to product delivery example in AnyLogic examples, there are two agents which are Retailer and Fulfillment center. Both have their own vehicles. What I'm trying to do is to share vehicles so retailers and Fulfillment centers use the vehicles of each others. What I did is to create two Ressource Pool in each agent. So in the seize block as it shown below in picture, I added two ressource sets . In each statechart of each vehicle as it shown below and after delievering products, I informed my vehicle to go back to his initial location and in this case it can be Retailer or Fulfillment center. However after simulation, I got an error message in console that tells me that my agent which is the vehicle is trying to move to unknown source
If you put 2 ResourcePools into 2 agents, you have 4 pools in total. But you only want 1 shared pool, right?
Only add 1 ResourcePool to Main and use that from both agent's Seize elements. You will not be able to select the pool in the usual dropdown list (as there is no pool in either agent) but you can easily use the dynamic code to specify it. Note that the code below assumes both agents are embedded in Main:

The storage does not contain the agent - Anylogic

I'm facing an issue with the project I'm developing using Anylogic.
I would like to have a rack store block and a rack pick block to select a pallet rack programmatically, choosing it from an array list.
In particular, rack store is working in this way:
rack store block
The rack pick block gives me an error, saying that the first pallet rack does not contain the agent, even though, by debugging, it says that that pallet rack has no free space and moreover the agents in it are of the correct type and the agent to be picked seems to be correctly positioned in the pallet rack.
The rack pick block is the following: rack pick block
The info I was talking about the item are visible here and I printed them with the following piece of code:
traceln(palletRackListKuka.get(0).getByIndex(0).agentInfo());
traceln("class is " + palletRackListKuka.get(0).randomAgent().getClass());
traceln("has space is " + palletRackListKuka.get(0).hasSpace());
How can I solve this? Please ask for further details in case I was not clear enough.
The way RackStore and RackPick work is that the agent flowing through the blocks is the one stored and picked.
Thus your error is likely because the pallet rack you choose (programmatically) in your RackPick block is not the same pallet rack you stored that agent in when it passed through the RackStore block earlier. Your console statements just show that the pallet rack has some agents of the required type, not the agent that is flowing through the RackPick block.
You can just add the pallet rack you stored the agent in as an extra field (variable) inside it, which you then reference when picking it.
Edit: To do that, you are already providing an expression for the pallet rack to store in, so instead make that a function call to a function you create (returning a type PalletRack) which selects the pallet rack and stores it in a type PalletRack variable inside your IndustrialContainer agent.
If you want 'decoupled' picking (i.e., what to pick is determined externally in some way) that is something different where you have to have some mechanism to then
choose which specific agent you want to pick (say out of 1000 instances of the same product) which will typically relate to your 'storage/retrieval policy';
'inject' that agent into a RackPick block to pick it (e.g., via an Enter block).
See the Distribution Center example model for a version of this.

How can I use rackPick block to seize more than one item at once? - Anylogic

I'm developing a project with Anylogic and I have an AGV with a Kuka cobot on top of it (a sort of mechanical arm used to pick item from a shelf, in this case) which should pick some items from a rack store. I would like the cobot to pick more than one single item at once.
The blocks I already put are shown in the picture and I thought that specifying "seize whole set at once" in the rackPick block would have helped but it did not.
Could you help me, please?
Thank you in advance.
The RackPick logic is agent-centric, i.e. the items in the rack are the active entities. They, essentially "pick themselves", optionally using your robot as a help.
So if you want your robot to pick several, it is best to batch your agents together before putting them into a rack (using Batch) and then let your robot pick that batch agent. You can unbatch into the original agents afterwards.
PS: That "seize whole set at once" option is again from the agent perspective: if it would need several resources to be picked, then this option would have an effect. In your case, with only needing 1 robot, it is meaningless

Prioritising pallet racks in a racking system

I am currently attempting to model a warehouse in AnyLogic. I have been using the Rack system with 5 pallet racks. I need the model to fill the pallet racks one at a time, i.e. currently when i initialise the model at 50% utilisation, all of the pallet racks are filled to 50% and i would like 2 and a half pallet racks to be filled up. Conversely, i would like the RackPick block to pick products from a single pallet rack until it is totally empty before it moves onto the next full pallet rack within the racking system. How can i achieve this? I am new to Anylogic.
I will show you how to do it with storing... You will have to do something similar with the picking.
You will need the following things:
Put the palletRacks in the order of priority in your rackSystem
Your agent will have a parameter called palletRack of type PalletRack with default value main.getPalletRack()
You need to create that getPalletRack function in main.
This function will use the following code:
for(PalletRack p : rackSystem.palletRacks){ //loops through the palletRacks of the rack system
if(p.hasSpace()) //checks if it has space
return p; // if it has space, return the palletRack
}
return null;
if you are familiar with this, you can also just have this in the function:
return findFirst(rackSystem.palletRacks,p->p.hasSpace());
Both do the same thing... but the second is not known by a new AnyLogic user
Finally:
In your rackStore, you will do the following:

Pick front item from a two deep pallet rack

I'm am storing agents two deep in a single pallet rack with a rackStore block. When I take items out of the rack with rackStore it tries the take the agents at the back first and I get the error below saying it couldn't be picked as there are other agents in front of it.
Anyone know how I can pick from the front instead?
This is big fail in the AnyLogic Software and it is something they have to fix urgently. Since when it comes to deep positions, you have to control everything manually.
I will give you an example that is definitely not optimal on how to solve your particular question and it will be just a step for you to understand how to extend it to something more than this. Because even though this should be a very easy question, it is not. This will work only 2 racks with 2 levels deep, 1 level of height, and a unique row.
So this is the structure you would need:
Since I have no idea how long your products stay on the rack, I will assume something, which is that with the event, I will make the decision on wether getting or not a product from the rack every 5 seconds (this is absolutely arbitrary).
You will need a custom agent to store the deep position. I call the agent Box and I will have a population of boxes. Not in the picture that I also add agents to the custom population boxes.The box agent will have 2 variables: deep and position which will store the position and deep level of the agent in the rack (you will need also level and row if you have a more complex rack)
Now on the event, which runs cyclically every 5 seconds, I have the following action: (it activates if there is a box waiting, if there is a resource available and if there is no forklift moving a product to the pallet rack) I have to do this because I cannot know where the forklift is going to put the box until the box is already in the pallet rack. Then I check if a box is not behind another with the findFirst function and if everything ok, a box is sent to be picked.
if(wait.size()>0 && resourcePool.idle()>0 && rackStore.size()==0){
Box bx=findFirst(wait,b->b.deep==0);
if(bx!=null)
wait.free(bx);
}
On the rackStore exit I need to store the positions so in the "on exit" action, this code will help (you check if there is another box in the same position, and if there is, you update the value of the deep variable. Then you store the value of the position and deep of the new agent)
Box box=findFirst(wait,b->b.position==position);
if(box!=null){
box.deep++;
}
agent.deep=0;
agent.position=position;
Finally on the rackPick on exit action, once the product is picked and delivered, you update the deep value of the box that was behind it (if any)
Box bx2=findFirst(wait,b->b.position==agent.position);
if(bx2!=null){
bx2.deep--;
}
I know all this looks a bit crazy, but you have to create all the logic yourself when it comes to using deep levels...