question

tomonori S avatar image
0 Likes"
tomonori S asked tomonori S commented

How to pick items based on distance?

Hi @Benjamin W2-san,
I have confirmed the model. Thank you very much.
We also need a sample model where the operator chooses a product based on distance.
Can the attached model include the ability for the operator to select products based on distance? Or can you include the ability for the operator to select products based on distance with something close to the "global-table-in-picking-model-with-row-batching.fsm" created?

Also, I would like to reduce the number of items on top of the attached image like "img_01.PNG".
Next week, we will visit potential customers, so I would like to receive an answer as soon as possible.

demo-ver03.fsm

img-01.png

img.png

FlexSim 18.0.10
global tablepickingdistance
5 |100000

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

1 Answer

Benjamin W2 avatar image
0 Likes"
Benjamin W2 answered tomonori S commented

Hi @tomonori S,

Picking Based on Distance

The key to ordering the orders by distance is to write custom code. From the attached model, in the Create Orders box, select the Create Object, add a label to the created items called "Rack" with a value of "Table("ItemLocation").executeCell(token.TaskRank, "Rack")". This will store the rack into the order.

In the Pickers Pull Orders and Items box, add an Assign Labels activity after the first Pull from List. The purpose of this activity is to re-order all of the pulled orders based on distance. Notice that this will only order the pulled orders.

Open up the Assign Labels activity. Add a label called "OrderedOrders". Select the arrow underneath "Value". Hover over "Array" and click "Create an Array of Values". Then click on the custom code icon. Delete the text of the custom code and past the following:

/**Custom Code*/
Object current = param(1);
treenode activity = param(2);
Token token = param(3);
Variant assignTo = param(4);
string labelName = param(5);
treenode processFlow = ownerobject(activity);
int orderArraySize = token.Orders.length;
Array orderedOrders = Array(0);
Array Orders = token.Orders;
Object aquiredOperator = token.Picker.as(Object);
double shortestDistance = 0.0;
int shortestIndex = 0;
for (int i = 1; i <= Orders.length; i++)
{
	double tempDistance = 0.0;
	Object object1 = aquiredOperator;
	Object object2 = Orders[i].Rack;
	double x1 = vectorprojectx(object1, 0.5 * xsize(object1), -0.5 * ysize(object1), 0, model());
	double y1 = vectorprojecty(object1, 0.5 * xsize(object1), -0.5 * ysize(object1), 0, model());
	double z1 = vectorprojectz(object1, 0.5 * xsize(object1), -0.5 * ysize(object1), 0, model());
	double x2 = vectorprojectx(object2, 0.5 * xsize(object2), -0.5 * ysize(object2), 0, model());
	double y2 = vectorprojecty(object2, 0.5 * xsize(object2), -0.5 * ysize(object2), 0, model());
	double z2 = vectorprojectz(object2, 0.5 * xsize(object2), -0.5 * ysize(object2), 0, model());
	tempDistance = sqrt(sqr(x1 - x2) + sqr(y1 - y2) + sqr(z1 - z2));
	if ((i == 1) || (tempDistance < shortestDistance))
	{
		shortestDistance = tempDistance;
		shortestIndex = i;
	}
	if (i == Orders.length)
	{
		orderedOrders.push(Orders[shortestIndex]);
		Orders.splice(shortestIndex,1);
	}
}
for (int i = 1; i <= orderedOrders.length; i++)
{
	double tempDistance = 0.0;
	Object object1 = orderedOrders[i].Rack;
	for (int j = 1; j <= Orders.length; j++)
	{
		Object object2 = Orders[j].Rack;
		double x1 = vectorprojectx(object1, 0.5 * xsize(object1), -0.5 * ysize(object1), 0, model());
		double y1 = vectorprojecty(object1, 0.5 * xsize(object1), -0.5 * ysize(object1), 0, model());
		double z1 = vectorprojectz(object1, 0.5 * xsize(object1), -0.5 * ysize(object1), 0, model());
		double x2 = vectorprojectx(object2, 0.5 * xsize(object2), -0.5 * ysize(object2), 0, model());
		double y2 = vectorprojecty(object2, 0.5 * xsize(object2), -0.5 * ysize(object2), 0, model());
		double z2 = vectorprojectz(object2, 0.5 * xsize(object2), -0.5 * ysize(object2), 0, model());
		tempDistance = sqrt(sqr(x1 - x2) + sqr(y1 - y2) + sqr(z1 - z2));
		if ((j == 1) || (tempDistance < shortestDistance))
		{
			shortestDistance = tempDistance;
			shortestIndex = j;
		}
		if (j == Orders.length)
		{
			orderedOrders.push(Orders[shortestIndex]);
			Orders.splice(shortestIndex,1);
		}
	}
}

Note that the above code will order the orders by looking first at the closest item to the operator, then the next closest item, then the next closest item. If you are looking for the shortest possible path, you will need to completely rebuild the model and design it for the optimizer.

Next, open up the Assign Labels in the first sub-flow underneath Pickers Pull Orders and Items. Underneath the label called "PullLable", edit the value to say, "token.parent.OrderedOrders[token.Rank].Label". Underneath the label "PullQuantity" edit the value to say, "token.parent.OrderedOrders[token.Rank].Quantity.

This will give you a better travel path than before.

Creating Different Number of Items

To reduce the number of items created within each rack, simply edit the "instructions" column within the table ItemLocation. Make sure that the value of this column is equal to or exceeds that of the "quantity" column or else the model will break.

global-table-in-picking-model-with-row-batching-an.fsm


· 5
5 |100000

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

tomonori S avatar image tomonori S commented ·

I have confirmed the model. Thank you very much.

In the simulation, the operator sometimes picks up the item without going to the front of the rack. Can this movement be made to go to the front of the rack and pick it up?

Also, is it difficult to rebuild the model for the optimizer if you want to find the shortest route?

0 Likes 0 ·
Benjamin W2 avatar image Benjamin W2 tomonori S commented ·

Hi @tomonori S, to make operators go to the front of the rack, make sure all racks are connected to the AStarNavigator.

In order for this model to run on the optimizer, we would most likely have to completely start over and re-design the logic. However, I believe that it is possible.

0 Likes 0 ·
tomonori S avatar image tomonori S commented ·

Hi Benjamin-san,
If the same part number is duplicated as in the attached image, it will be two pickings. Can you combine them into one picking?
In addition, it is a movement to direct the operator to the front of the rack. How should I connect the rack and AStarNavigator?

img.png

0 Likes 0 ·
img.png (195.6 KiB)
Benjamin W2 avatar image Benjamin W2 tomonori S commented ·

Hi @tomonori S-san,

Yes, you should be able to fix this very easily. Notice that the row headers are the same, but the "OrderID" column is different. It looks like order 82 maps to OrderID 6. simply change the first red box to have an OrderID of 6 and you should be good to go.

To connect the rack to A*, simply make A-connections from each rack to the A* in the 3D model.

0 Likes 0 ·
tomonori S avatar image tomonori S commented ·

We changed order 82 to order ID 6, but we were not able to combine them into one picking.
Also, because I do not know how to direct the operator to the front of the rack, could you improve the attached model?

img.png

test-01.fsm

0 Likes 0 ·
test-01.fsm (84.5 KiB)
img.png (170.4 KiB)