question

Dirk Boumans avatar image
0 Likes"
Dirk Boumans asked Jeanette F commented

hasSpace returns unexpected value

Hi,

I'm using a FloorStorage inside a taskexecuter flowitem to simulate a container vessel for a port simulation model. The objective for the model is to simulate the utilization of equipment such as cranes and trucks inside a container port. The reason for using a FloorStorage inside the flowitem is that it allows me to store containers in specific slots and positions on the vessel and find containers in specific slots which is easier than of using the packing method on a flowitem.

The downside of this method is that it doesn't allow me to use the "Find Slot" and "Find Item" functions in Process Flow because only the storageObjects in the flowitembin are add to the StorageSystem in the tree. The storageObjects in flowitems created in the model are not added to the tree and can't be queried with the basic functions. It would be a bonus if someone knows a way to get these items added in the tree and it would be possible to use the basic functions.

My solution to this is to use custom code and point to the specific subnodes (FloorStorage) on the flowitem to assign slots to items. This works as intended but now I've come across a problem I can't figure out.

First I'll start with explaining my approach and then I'll come to the problem.

When a vessel arrives at the port I create the vessel flowitem and create a container flow items for each 20ft and 40 ft container on the vessel. When I search for a slot on the vessel I do this first for the front deck and than for the rear deck because these are two different FloorStorage objects inside the vessel. I use the following code FindRandomSlotVesselCreation.png

findrandomslotvesselcreation.png

This works as long as the number containers doesn't exceed the storage capacity. When the vessel arrives I create a shopping list for the containers which need to be loaded onto the vessel after unloading is finished. The shopping list looks for the same amount of 20 and 40 foot containers but will have different distributions of empty and full containers depending on the destination of the vessel. Once I have the shopping list I search the container yard for the appropriate containers and put them on the list. After the ship is unloaded I start to process of assigning storage slots to the containers. This can only be done after the ship is empty because otherwise the ship will be to full and containers will not receive a slot.

In this last process is where I encounter a problem which I don't understand. The code for finding slots is almost identical as the one used when the vessel is created. Find Random Slot Cargo - Custom Code.png However the difference is that the item state is different and the container is not created in the model but already stored in a FloorStorage object in the container yard. After 196 containers at time (61666.25) it fails to assign slots to 40ft containers and when I look into this it seems that the following evaluation gives an unexpected result:

if(!slot.isStorable || !slot.hasSpace(item))
 continue;

The result of the if statement keeps being true and therefore the while loop will run until the counter is at 10001 and then stops.

When I look into this the "!slot.hasSpace(item)" returns 1 which I can't explain. When I check the last container it evaluated and the last slot it evaluated I come to the conclusion that:

  1. The slot is storable so !slot.isStorable return false, which is good
  2. The !slot.hasSpace returns 1. However it only has 1 40ft container assigned to it so should return false. The size of the slot is [14.2, 2.5, 12.5] and a 40ft container is [12.2, 2.44, 2.5].
  3. The slot has 1 item of the same Type
  4. The orientation of the item is equal to all previous containers so the orientation can't be the reason the slot doesn't have space.

So in my view the slot must have been assigned to the item but it didn't. Can someone help me with figuring out why this happens?

slothasSpace.fsm

FlexSim 23.1.0
storage systemhasspace
· 1
5 |100000

Up to 12 attachments (including images) can be used with a maximum of 23.8 MiB each and 47.7 MiB total.

Jeanette F avatar image Jeanette F ♦♦ commented ·

Hi @Dirk Boumans, was one of Joerg Vogel's or Felix Möhlmann's answers helpful? If so, please click the "Accept" button at the bottom of the one that best answers your question. Or if you still have questions, add a comment and we'll continue the conversation.

If we haven't heard back from you within 3 business days we'll auto-accept an answer, but you can always unaccept and comment back to reopen your question.

0 Likes 0 ·
Felix Möhlmann avatar image
0 Likes"
Felix Möhlmann answered Dirk Boumans edited

I believe it might be a floating point precision issue. After I reduced the slot padding to 0.99m on both sides instead of 1m, all containers were assigned successfully.

Alternatively, you could just not use hasSpace and instead hard code the limit per slot depending on whether it contains 20ft or 40ft containers.

...
    if(!slot.isStorable) /* When the selected slot is Not storabel or has Not enough space the for function continues to the next value*/
        continue;     if(slot.slotItems.length > 0)     {         if(slot.Type != item.Type)         {             continue;         }         if((slot.Type == "20ft" && slot.slotItems.length < 8) || (slot.Type == "40ft" && slot.slotItems.length < 4))         {             storageItem.assignedSlot = slot;             return 0;         }     }     else     {         storageItem.assignedSlot = slot;         slot.Type = item.Type;         return 0;     } ...

There are a couple of ways to get the storages added to the storage system.

- Create them separately through Object.create() and then move them into the vessel.

- There is some command that is executed when an object is added, but I can't remember the details right now (some function_s() or similar). Looking for similar topics that add storage objects via code might yield a result.

- Manually add the coupling nodes to the tree by code.

treenode storageSystemObjects = Model.find("/Tools/StorageSystem>variables/storageObjects");
treenode systemNodeStore1 = token.ship.subnodes[1].find(">variables/system"); treenode systemNodeStore2 = token.ship.subnodes[2].find(">variables/system"); createcoupling(storageSystemObjects, systemNodeStore1); createcoupling(storageSystemObjects, systemNodeStore2);
· 4
5 |100000

Up to 12 attachments (including images) can be used with a maximum of 23.8 MiB each and 47.7 MiB total.

Dirk Boumans avatar image Dirk Boumans commented ·

Felix, thanks for the answer.

I thought the slot padding suggestion did the trick but now I encounter the same problem when increasing the total number of containers to 1381 (643 20ft and 738 40ft.). It fails after 206 containers (time 123574). I've tried changed the slot padding size, slot size and removing the slot padding. Still the same result. So it looks to me that this doesn't solve the hasSpace issue.

I'll try your workaround with the hard coded maximum number of 20 or 40 ft containers per slot and leave the hasspace function out. This way I can continue but it doesn't solve the problem. I don't prefer to code it like this because this means that all ships will have this limitation where this differs from ship to ship.

0 Likes 0 ·
Felix Möhlmann avatar image Felix Möhlmann Dirk Boumans commented ·

Instead of hardcoding the limit, you could of course also calculate it based on the height of the storage. (Essentially build your own basic 'hasSpace' function)

double containerHeight = item.size.z;
int limit = token.Deck.size.z/containerHeight; if((slot.Type == "20ft" && slot.slotItems.length < limit*2) || (slot.Type == "40ft" && slot.slotItems.length < limit))
{     storageItem.assignedSlot = slot;     return 0; }

That way differences between the ships are taken into account automatically.

0 Likes 0 ·
Joerg Vogel avatar image Joerg Vogel Dirk Boumans commented ·

A floorstorage has got a dimension in z, which is evaluated by hasSpace() method. Curently I try to stack items of a length of 1 or 2 in slots of a x-size of 2. All I get to work is, so that items of same size can occupy a slot. I want to mix them but without a creation of holes in the front view. currently slots are assigned in On Entry Trigger of Queue1.

fill_vessel_rack_simple.fsm


0 Likes 0 ·
Dirk Boumans avatar image Dirk Boumans Joerg Vogel commented ·

Thanks Felix and Joerg,

My reply yesterday was in hindsight a bit to quick. What I did was changing the dimensions of the slotpadding and slotsize in the tree (the node in flowitembin). tree.png

When I do it like this it is not fool proof. When I create a new flowitem and put in new floorstorages with same dimensions as above it works flawless. So solution works.

0 Likes 0 ·
tree.png (7.0 KiB)
Joerg Vogel avatar image
0 Likes"
Joerg Vogel answered

I tried to get a flowitem with a floorstorage available in FlexSim Warehouse system.

Racks get a unique name. They are coupling nodes established to rack and StorageSystem [Tools].

On Create Trigger of a source

/**activate storageSystem*/
Object current = ownerobject(c); Object item = param(1); int rownumber = param(2); //row number of the schedule/sequence table item.first.name="StorageVessel"+numtostring(current.index); current.index++; // unique name attribute treenode system = item.first.find(">variables/system"); treenode warehouse = Model.find("Tools/StorageSystem>variables/storageObjects"); createcoupling(system,warehouse);

source label "index" added.

floorStorageOnItem.fsm


5 |100000

Up to 12 attachments (including images) can be used with a maximum of 23.8 MiB each and 47.7 MiB total.