Hi @霈倫,
I changed your model to better accomodate the large number of storage objects. The assumption was that the "DstY" value denotes the row number of the storage the pallet should be transported to.
Most of the code is still in the "Decide Storage" activity. I'll also post it below. The comments should hopefully explain what each part of the code does.
Furthermore I replaced almost all direct references to the cars by assigning the correct the ones to token labels based on the destination. This should make adding cars for the fourth level easier.
The "MomCar" can be a copy of one of the three existing one with the name "MOM CAR4". The "SonCar" must be connected to the "MomCar" with a center connection (s-connection).
Because the references to the transporters are updated according to the destination, a single process flow can handle all transports. I also added the MomCars as a resource so the model can be expanded to allow for multiple simultaneous transports more easily.
If you have a specific questions about the code or other parts of the model feel free to ask.
0826new-2-4-fm-1-3.fsm
"Decide Storage" Code:
**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);
Object FloorStorage; // This will store the floor storage the pallet should be stored in
/*
The assumption for this code is that the name of the floor storage can be reconstructed from the Dst values on the pallet.
DstX determines whether the floor storage is on the left or right (L or R), DstY the first number and DstZ the floor number.
-> The name takes the form of "FloorStorage_ + (L or R depending on DstX) + DstY + _ + DstZ + F"
DstX furthermore determines the bayID of slot, values of the 1-13 belong to the left storage and correspond to the bayID, 14-26
belong to the right storage and count the bayID from the right (14 -> ID 13, 15 -> ID 12, ...)
*/
string StorageName = "FloorStorage_"; // We start with the common part of the floor storage name
// Now we add the variable parts to the string (text) variable
// First the side, if DstX is larger than 13, we add an R to the name, otherwise an L
if(token.DstX > 13)
{
StorageName = StorageName + "R";
}
else
{
StorageName = StorageName + "L";
}
// Now add the y coordinate, the number value must first be converted into a string (text) value. We also add the second underscore to the name here.
StorageName = StorageName + string.fromNum(token.DstY, 0) + "_";
// Finally, add the floor number. Similar to the y coordinate we must convert the variable type
StorageName = StorageName + string.fromNum(token.DstZ, 0) + "F";
// Now we have the final name of the destination storage and can use it to get a reference to the storage object in the model
FloorStorage = Model.find(StorageName);
// Next, we assign the bayID.
int bayID = token.DstX;
if(bayID > 13)
{
// If right side, DstX counts from right
bayID = 13 - (token.DstX - 14);
}
/*
Now we can assign the item to the correct slot. There are two ways to move an item into a specific slot of a storage object.
The first is to use the "Slot Assignment Strategy" of the storage object ("Storage Object" tab in its properties window). The option
"By Bay, Level, Slot ID" allows to define the slot the item should enter via labels on the item itself.
As we want to get the actual 3D position of the slot so we can have the cars drive there, we need to get a reference to the slot anyway and can
use the second way to assign a specific slot: Set it in code before item enters the storage object
*/
// Get reference to slot class object, as there is only one slot per level and one level per bay, the bayID directly defines the slot
Storage.Slot slot = FloorStorage.as(Storage.Object).bays[bayID].levels[1].slots[1];
// Create storage.item class object for pallet. This is an internal representation of the item to keep of track of where in the storage system it is.
Storage.Item storageItem = Storage.Item(token.PulledItem);
// This storage.item can then be assigned the slot it is bound for. If the item now enters the respective storage object, it will overwrite the Slot Assignment strategy
storageItem.assignedSlot = slot;
// Assign MomCar to token label, so we can reference it more easily in the travel activities. We again use the DstZ value to get the name of the Mom Car.
// As such it is important that they are numbered from 1 to 4 in their names
token.MomCar = Model.find("MOM CAR" + string.fromNum(token.DstZ, 0));
// The SonCar is connected to each MomCar via an s-connection and can thusly be referenced that way.
token.SonCar = token.MomCar.as(Object).centerObjects[1];
// Get distance between slot and MomCar on x-axis (distance SonCar has to travel)
token.DstX = -(token.MomCar.as(Object).getLocation(0.5, 0.5, 0).x - slot.getLocation(0.5, 0.5, 0.5).project(FloorStorage, model()).as(Vec3).x);
// Assign y-location of slot
token.DstY = slot.getLocation(0.5, 0.5, 0.5).project(FloorStorage, model()).as(Vec3).y - 1;
return FloorStorage;